BullMQ
BullMQ Nedir?
BullMQ, Node.js uygulamalarında zaman alan, kullanıcıyı bekletmemesi gereken ve retry gerektiren işlemleri arka planda çalıştırmak için kullanılan Redis tabanlı bir job queue sistemidir.
Kullanım amacı:
“Bu işlemi yapmam gerekiyor ama kullanıcıyı bekletemem.”
Örnek senaryolar:
- E-posta gönderimi
- Video işleme
- PDF / rapor oluşturma
- Büyük dosya yükleme
- Toplu bildirim gönderimi
- Ödeme sonrası async işlemler
Neden Direkt API İçinde Yapmayız?
Node.js single-thread mimariye sahiptir. Eğer ağır bir işlemi request içinde yaparsak:
- Kullanıcı uzun süre response bekler
- Aynı anda gelen diğer istekler bloklanabilir
- CPU %100 olabilir
- Server restart olursa işlem kaybolur
BullMQ bu problemleri çözer.
Neden BullMQ Kullanırız?
BullMQ’nun sağladıkları:
- Redis tabanlı (in-memory, hızlı)
- At-least-once delivery
- Retry & backoff
- Delayed jobs
- Rate limiting
- Worker separation
- Concurrency kontrolü
- Atomic operations
Mimari
API Server → Queue (Redis) → Worker
| Bileşen | Görevi |
|---|---|
| Producer | Job üretir (API) |
| Queue | Redis üzerinde job saklar |
| Worker | Job’u işler |
| Job | Yapılacak iş |
| Retry | Hata sonrası tekrar |
| Delay | Gecikmeli job |
| Backoff | Retry aralığı |
| Rate Limit | Job hız limiti |
Producer – Queue – Worker Nasıl Çalışır?
1. Producer
API içindeki kod job oluşturur ve kuyruğa ekler.
Örneğin: “Bu kullanıcıya hoş geldin maili atılacak.”
2. Queue (Redis)
- Job’ları saklar
- Sıralar
- Hangi job bekliyor, hangisi tamamlandı takip eder
3. Worker
- Arka planda çalışır
- Queue’yu dinler
- Job geldiğinde gerçek işlemi yapar
Önemli Özellikler
Retry (Tekrar Deneme)
Mail servisi kapalıysa:
- 3 kez dene
- 5 saniye arayla dene
Delayed Jobs
- “24 saat sonra hatırlatma maili gönder.”
Priority
- VIP kullanıcıların işleri önce işlensin.
Concurrency
- Worker aynı anda kaç job işlesin?
- Örneğin 5 video paralel işlenebilir.
Örnek Kullanım
Producer
const myQueue = new Queue('mail-queue', { connection: redisConnection });
await myQueue.add('welcome-email',
{ userId: 1, email: 'test@test.com' },
{
attempts: 3,
backoff: 5000
}
);
Worker
const worker = new Worker(
'mail-queue',
async job => {
console.log(`Sending email to ${job.data.email}`);
},
{ connection: redisConnection }
);
E-Commerce Örneği
// queue.js
export const orderQueue = new Queue('orderQueue', {
connection: { host: 'localhost', port: 3003 }
});
// timeout-worker.js
const worker = new Worker(
'orderQueue',
async (job) => {
const { orderId } = job.data;
await OrderService.cancelIfNotPaid({ orderId });
},
{ connection: { host: 'localhost', port: 3003 } }
);
Örnek senaryo:
- Kullanıcı sipariş verdi
- 15 dakika ödeme yapmazsa sipariş iptal edilecek
- Bu işlem background job ile yapılır
Redis Neden Kullanılır?
- In-memory → Çok hızlı
- Atomic operations → Race condition engellenir
- Distributed lock mantığı sağlar
- Multiple worker güvenli şekilde çalışabilir
Bir job’un iki worker tarafından aynı anda işlenmesini Redis engeller.
BullMQ Kullanmazsak Ne Olur?
- Kullanıcı response bekler
- CPU yükselir
- Server restart olursa job kaybolur
- Retry mekanizması olmaz
- İşler sessizce fail olabilir
Monitoring Neden Şart?
Background job’lar:
- Request’e bağlı değildir
- Sessizce fail olabilir
- Kullanıcı fark etmeyebilir
Monitoring yoksa problem fark edilmez.
BullMQ Dashboard (Arena)
npm install bull-arena
app.use(
"/bullmq-dashboard",
Arena(
{
BullMQ: require("bullmq"),
queues: [{ name: "testQueue", hostId: "Main Server" }],
},
{ basePath: "/bullmq-dashboard", disableListen: true }
)
);
Dashboard üzerinden:
- Bekleyen job’lar
- Başarılı job’lar
- Fail olan job’lar
- Retry sayıları
görülebilir.
Message Queue Kavramı
| Rol | Açıklama |
|---|---|
| Producer | Mesajı üretir |
| Broker | Mesajı saklar ve iletir (Redis) |
| Consumer | Mesajı işler |
Bu yapı sadece BullMQ değil, Kafka ve RabbitMQ gibi sistemlerde de geçerlidir.