.NET 10 Minimal API ile RabbitMQ: publisher confirm, retry ve dead-letter queue
Çoğu RabbitMQ örneği "Hello World" seviyesinde kalır; gerçek servislerde mesaj kaybı, sağlayıcı kesintisi ve kalıcı hata durumlarının da ele alınması gerekir. Bu makale, .NET 10 Minimal API üzerinde sipariş endpoint'i, publisher confirm, 10 saniyelik gecikmeli retry kuyruğu ve dört denemeden sonra mesajların düştüğü bir dead-letter queue ile tam bir akış kuruyor.
Kilit noktalar
- Publisher confirmations ve tracking'i açan CreateChannelOptions ile BasicPublishAsync broker onayı gelene kadar bekliyor; mesaj kaybı bu noktada yakalanıyor
- Retry kuyruğu consumer'sız çalışıyor: x-message-ttl 10000 milisaniye süresi dolan mesaj dead-letter ile asıl kuyruğa geri dönüyor
- Deneme sayısı broker'ın requeue davranışına bırakılmıyor, x-attempt header'ı ile uygulama tarafında tutuluyor; sınır 4 deneme
- Bozuk JSON retry edilmiyor, BasicRejectAsync ile doğrudan reddediliyor çünkü tekrar denemek hatayı düzeltmez
- Kuyruklar quorum tipinde tanımlanıyor ve dayanıklılık için DeliveryMode.Persistent kullanılıyor
- Tek bağlantı lazy oluşturuluyor ve AutomaticRecoveryEnabled açık; kanallar ise semaphore ile serileştiriliyor
Örnek, RabbitMQ.Client 7.2.2 ile .NET 10 üzerinde topic exchange (orders), quorum kuyruklar ve fanout bir dead-letter exchange'den oluşan bir topoloji kuruyor. Publisher tarafında CreateChannelOptions üzerinden publisher confirmation ve tracking açılıyor; böylece BasicPublishAsync ancak broker mesajı onayladıktan sonra tamamlanıyor, mandatory: true ise hiçbir kuyruğa uymayan mesajın sessizce kaybolmasını engelliyor. Tek bir uzun ömürlü bağlantı ilk kullanımda oluşturulduğu için uygulama broker kapalıyken de açılabiliyor.
Consumer bir BackgroundService: başarılı mesaj acknowledge ediliyor, bozuk JSON hemen reddediliyor, hata alan mesaj x-attempt header'ı artırılarak TTL'i 10 saniye olan retry kuyruğuna yazılıyor ve süre dolunca varsayılan exchange üzerinden asıl kuyruğa geri düşüyor. Dördüncü denemede hâlâ başarısız olan mesaj dead-letter kuyruğuna gidiyor. Dikkat: kanal thread-safe değil, bu yüzden publisher ve consumer tarafında kanal semaphore ile korunuyor; ayrıca retry mesajı orijinal mesaj acknowledge edilmeden önce yayınlanıyor, bu da olası çift işlemeyi kayba tercih eden bilinçli bir tercih.
Gerçek dünyada kullanımı
- Sipariş oluşturulduğunda e-posta veya fatura üreten ve sağlayıcı kesintilerinde mesajı kaybetmemesi gereken bir e-ticaret backend'i
- Dış API'ye bağımlı arka plan işlerinde kalıcı hataları dead-letter kuyruğuna ayırıp elle inceleme yapan operasyon ekibi
- Yüksek trafikte kuyrukları RabbitMQ üzerinden ayıran çok servisli bir .NET çözümünde dayanıklı event yayınlama
- Kurumsal entegrasyonlarda bozuk veya şeması değişmiş mesajları ana akışı bloke etmeden izole etmek
Neden önemli
Bu üç mekanizma (confirm, gecikmeli retry, dead-letter) olmadan kuyruk tabanlı bir servis sessizce mesaj kaybeder ya da aynı hatayı sonsuza dek tekrarlar; makale bunların .NET 10 ve RabbitMQ.Client 7.x'te nasıl birlikte kurulacağını gösteriyor.