ایجاد Queue با Bull در Node.js
Bull یک کتابخانهٔ محبوب برای مدیریت صفکاری (job queue) در محیط Node.js است که از Redis بهعنوان بکاند استفاده میکند. با Bull میتوانید کارهای وقتگیر یا پرهزینه مانند ارسال ایمیل، پردازش تصویر، ایجاد گزارش و وظایف زمانبندیشده را بهصورت غیرهمزمان اجرا کنید و از قابلیتهایی مانند retries، backoff، زمانبندی و مانیتورینگ بهرهمند شوید.
چرا از Bull استفاده کنیم؟
- پایداری بالا با استفاده از Redis
- پشتیبانی از تلاشهای مجدد (retries) و الگوریتمهای backoff
- قابلیت اجرای موازی با تعیین concurrency
- قابلیت زمانبندی (delay/repeat) و اولویتبندی
- سازگاری آسان برای جداسازی producer و worker (مناسب برای microservices)
نصب و آمادهسازی (Prerequisites)
قبل از هر چیز باید Redis را روی سیستم یا سرویس ابری داشته باشید و سپس بستهٔ Bull را نصب کنید:
npm install bull
کد بالا Bull را نصب میکند. مطمئن شوید Redis در آدرس پیشفرض (127.0.0.1:6379) یا آدرس دلخواه شما در دسترس است.
نمونهٔ پایه — تولیدکننده (Producer)
// producer.js
const Queue = require('bull');
const emailQueue = new Queue('email', {
redis: { port: 6379, host: '127.0.0.1' }
});
async function addEmailJob(to, subject, body) {
await emailQueue.add(
{ to, subject, body },
{
attempts: 3,
backoff: { type: 'exponential', delay: 5000 },
removeOnComplete: true,
delay: 1000
}
);
}
addEmailJob('user@example.com', 'Welcome!', 'Thanks for joining.')
.then(() => console.log('job added'))
.catch(console.error);
توضیح: در این کد یک صف به نام “email” ساخته میشود. تابع addEmailJob یک job با دادههای ایمیل اضافه میکند و تنظیماتی مثل attempts (تعداد تلاشها)، backoff (استراتژی تأخیر بین تلاشها)، removeOnComplete (حذف خودکار پس از انجام) و delay (تأخیر اجرای اولیه) مشخص شده است.
نمونهٔ پایه — پردازشگر (Worker)
// worker.js
const Queue = require('bull');
const emailQueue = new Queue('email', {
redis: { port: 6379, host: '127.0.0.1' }
});
emailQueue.process(5, async (job) => {
// job.data contains { to, subject, body }
console.log('Processing job', job.id, job.data);
// مثال: ارسال ایمیل فرضی
await sendEmail(job.data);
return { ok: true };
});
emailQueue.on('completed', (job, result) => {
console.log(`Job ${job.id} completed`, result);
});
emailQueue.on('failed', (job, err) => {
console.error(`Job ${job.id} failed`, err);
});
// Graceful shutdown
process.on('SIGINT', async () => {
console.log('Closing queue...');
await emailQueue.close();
process.exit(0);
});
async function sendEmail({ to, subject, body }) {
// شبیهسازی ارسال ایمیل
await new Promise(r => setTimeout(r, 1000));
}
توضیح: این فایل به صف “email” کانکت میشود و تا 5 پردازش همزمان (concurrency) را قبول میکند. در callback پردازش، میتوانید منطق واقعی ارسال ایمیل یا هر پردازش دیگر را بنویسید. گوش دادن به رویدادهای completed و failed به شما کمک میکند عملیات مانیتورینگ و لاگینگ را انجام دهید. در انتها با بستهشدن (close) صف، فرآیند بهصورت صحیح خاموش میشود.
ویژگیهای مهم و تنظیمات رایج
| گزینه | توضیح |
|---|---|
| attempts | تعداد تلاشهای مجدد برای job در صورت شکست |
| backoff | نوع و تأخیر بین تلاشهای مجدد (fixed یا exponential) |
| delay | تأخیر اولیه قبل از اجرای job (میلیثانیه) |
| removeOnComplete | حذف خودکار job پس از تکمیل برای جلوگیری از افزایش حافظهٔ Redis |
| priority | اولویتبندی jobها (مقدار عددی) |
| repeat | برای jobهای زمانبندیشده یا تکراری (cron یا هرچند میلیثانیه) |
استفادههای متداول و الگوهای طراحی
- ارسال ایمیل یا نوتیفیکیشن بعد از ثبتنام
- پردازش تصاویر یا ویدئو در پسزمینه (تبدیل فرمت، thumbnail)
- تجمیع گزارشها و اجرای وظایف زمانبندیشده
- مسیریابی کاری به workerهای جدا در سرویسهای مختلف (microservices)
نکات عملی و بهینهسازی
- جداسازی producer و worker: workerها را در پروسس/کانتینر جدا اجرا کنید تا عدم قطع سرویس تولیدی تضمین شود.
- حذف jobهای قدیمی: با removeOnComplete یا فرمانهای پاکسازی در Redis حجم را کنترل کنید.
- نظارت: از ابزارهایی مثل Bull Board یا Arena برای مشاهدهٔ صفها و jobها استفاده کنید.
- تنظیم concurrency: مقدار را متناسب با منابع (CPU/IO) و نوع کار تنظیم کنید؛ برای IO-bound بالاتر از CPU-bound است.
- امنیت Redis: در تولیدی حتماً Redis را با پسورد و اتصال امن محافظت کنید.
مثال پیشرفته — ارسال وضعیت پیشرفت (progress)
emailQueue.process(async (job) => {
for (let i = 0; i setTimeout(r, 200));
job.progress(i);
}
return { sent: true };
});
emailQueue.on('progress', (job, progress) => {
console.log(`Job ${job.id} is ${progress}% done`);
});
توضیح: با استفاده از job.progress میتوان پیشرفت کار را بهروزرسانی کرد و در سمت مانیتورینگ یا API وضعیت را نمایش داد. این روش برای عملیات طولانی مانند آپلود یا پردازش ویدئو مفید است.
موارد احتیاطی و مسائل رایج
- مسائل مربوط به stalled jobs: اگر worker بهطور ناگهانی قطع شود، Bull تلاش میکند job را مجدد اجرا کند؛ اما تنظیمات مربوط به بازهٔ تشخیص stalled را بررسی کنید.
- وابستگیها: اگر jobها وابستگیهای پیچیده دارند، بهجای Bull ممکن است بخواهید BullMQ یا سیستمهای کاری DAG را بررسی کنید.
- مقیاسپذیری Redis: در بار بالا باید Redis را برای مقیاسپذیری و پایداری مناسب پیکربندی کنید (پیکربندی حافظه، persistence، clustering).
نتیجهگیری
Bull یک ابزار قدرتمند و عملی برای مدیریت صف و پردازش پسزمینه در Node.js است. با اتصال ساده به Redis، امکاناتی مانند retry، delay، concurrency و رویدادها را فراهم میکند که آن را برای بسیاری از اپلیکیشنها مناسب میسازد. با رعایت نکات عملیاتی مانند جداسازی workerها، مانیتورینگ و تنظیم درست Redis میتوان سیستم قابل اعتمادی با Bull ساخت.
آیا این مطلب برای شما مفید بود ؟




