İki Kuyruk: BullMQ ve RabbitMQ Aynı Projede Ne İşe Yarıyor

/engineering

Geçen gün ekibe yeni katılan bir arkadaş kod tabanına bakarken sordu: "Burada niye iki tane kuyruk var, biri yetmiyor mu?" Gayet haklı bir soru. Ben de ilk gördüğümde aynısını düşünmüştüm, hatta içimden "bunu kim böyle kurmuş ya" diye geçirmiştim. Sonra anladım ki ikisi aynı işi yapmıyor.

Prisync'te hem BullMQ hem RabbitMQ var. Yan yana, aynı sistemde. Kazara birikmiş bir teknik borç değil bu; oturup tartışılmış bir tercih. Anlatmak istiyorum çünkü "tek kuyruk yeter" lafı kulağa hep temiz geliyor ama çoğu zaman yanlış.

İkisi aynı şey değil

BullMQ, Redis'in üstünde duruyor. Kafanda bir iş listesi gibi canlandır: "şu ürünü çek", "şu raporu üret", "şu maili gönder". Redis hızlı, sen de retry, gecikmeli çalıştırma, tekrar eden işler... hepsini paket halinde alıyorsun. Bir Node servisine bağlaması yarım saat bile sürmüyor.

RabbitMQ başka bir şey. O işi yaptırmıyor, haberi taşıyor. "Bir ürünün fiyatı değişti" diye ortaya söylüyorsun, kim duyuyor senin umurunda değil. Bir servis dinler, beş servis dinler, altı ay sonra altıncısını eklersin — söyleyen taraf hiçbir şeyini değiştirmez. Routing, exchange, fanout, hepsi bunun için var.

Yani biri işi yapıyor, öbürü dedikoduyu yayıyor. İkisini tek araca sıkıştırmaya çalıştığım zamanlar oldu. Sonu hep aynı: ya kuyruğun içine girmemesi gereken bir bilgi sızdı, ya da küçücük bir job için koca bir broker'ı sırtımda taşıdım.

Peki nasıl ayırıyorum

Çok bilimsel bir şey değil aslında. Kafamdaki test şu kadar basit: iş bir servisin içinde başlayıp orada bitiyorsa, retry istiyorsa, "şunu on dakika sonra yap" diyorsam BullMQ. Bir şey olduysa ve bunu kimin önemseyeceğini bilmiyorsam RabbitMQ.

Fiyat çekmeyi düşün. "Şu ürünü çek" net bir iş. Retry'ı var, rate limit'i var, sıraya giriyor — bunların hepsi o işin kendi derdi. Tam BullMQ'luk. Ama çekim bitip de "fiyat değişti" olduğunda iş değişiyor. O haberle kim ne yapacak, çeken servisin gerçekten umurunda değil. Biri kullanıcıya bildirim atar, biri geçmişe yazar, biri başka bir şeyi tetikler. İşte orası RabbitMQ.

Bedava değil tabii

Burada dürüst olmam lazım. İki sistem demek, gece 2'de hangisinin patladığını ayırt etmeye çalışmak demek aynı zamanda. Redis dolduğunda yaşanan şey başka, RabbitMQ'da mesajlar sırada biriktiğinde yaşanan şey bambaşka. İkisinin de monitoring'ini ayrı kurmak, yeni gelen arkadaşa ikisini birden anlatmak zorundasın.

O yüzden kendime koyduğum kural basit: ortada gerçek bir sebep yoksa ikinciyi getirme. Küçük bir projede tek başına BullMQ fazlasıyla yeter. Kendi tarafımdaki işlerde sırf "olay yayınlıyorum" havası olsun diye RabbitMQ kurmam. İkinci kuyruk, birbirini gerçekten tanımayan servisler ortaya çıktığında anlam kazanıyor. Bir gün önce değil.

Aslında mesele kuyruk bile değil

Bir noktada fark ettim ki bütün bu tartışma araçla ilgili bile değil, sınır çizmekle ilgili. "Bu iş kimin sırtında başlayıp kimin sırtında bitiyor?" — buna verdiğin cevap zaten hangi kuyruğu seçeceğini de söylüyor. Sınırı net çizebiliyorsan araç kendiliğinden ortaya çıkıyor. Çizemiyorsan, hangisini koyarsan koy ortalık karışıyor.

Bana iki kuyruk tutmak fazladan yük gibi gelmiyor açıkçası. Daha çok sistemin kendi şeklini kabul etmek gibi. Bazı işler içeride sessizce bitiyor, bazıları dışarı bir şey haykırıyor. İkisini ayrı tuttuğumda hem kod hem kafam daha rahat oluyor.

Tek kuyruk yeter mi? Bazen yeter, valla. Ama "yeter" ile "doğru" her zaman aynı şey değil.