sazak@labs:~
oturum

etiketler

.NETölçeklenebilirlikmikroservisRabbitMQmesajlaşma

Software · Oct 15, 2026 · 4 dk okuma

RabbitMQ ile Event-Driven Architecture: .NET Mikroservislerinde Asenkron İletişim

RabbitMQ ile ölçeklenebilir iletişimin anahtarı queue eklemek değil, mesaj sözleşmesi ile teslimat davranışını birlikte tasarlamaktır.

RabbitMQ ile Event-Driven Architecture: .NET Mikroservislerinde Asenkron İletişim

RabbitMQ, mikroservisleri gevşek bağlı hale getirmez; doğru mesaj sınırları ve doğru teslimat davranışı getirirseniz bunu mümkün kılar. HTTP çağrısını bir queue ile değiştirmek, dağıtık sistem problemlerini ortadan kaldırmak yerine başka bir yere taşır.

Pazartesi yeni bir servis bağlantısı tasarlarken vereceğiniz temel karar şu olmalı: çağıran servis gerçekten anlık bir cevaba mı ihtiyaç duyuyor, yoksa gerçekleşmiş bir olayı mı yayımlıyor? İkinci durumda RabbitMQ güçlü bir adaydır, ancak publisher confirm, acknowledgment, retry ve idempotency de tasarımın parçasıdır.

Asıl sınır queue değil, servis sorumluluğudur

Senkron zincirler büyüdükçe bir servisin erişilebilirliği diğerlerinin çalışma koşuluna dönüşür. Order API'nin ödeme, stok ve bildirim servislerini sırayla HTTP ile çağırdığı bir akışta gecikmeler toplanır; geçici bir hata ise çağrı zincirinde retry ve timeout davranışlarını tetikler.

Yaygın düzeltme, bu HTTP çağrılarının her birini RabbitMQ mesajına çevirmektir. Bu yaklaşım bağımlılığın biçimini değiştirir ama sınırı düzeltmez. OrderCreated gibi geçmişte gerçekleşmiş bir olayı yayımlamak ile ReserveStock gibi başka bir servisten iş isteyen komut aynı şey değildir.

Event gönderen servis, consumer'ların kim olduğunu bilmemelidir. Komutta ise belirli bir işi bir consumer'ın üstlenmesi beklenir. Exchange, routing key ve queue topolojisini bu ayrımdan sonra seçmek, broker ayrıntılarının domain tasarımını yönetmesini engeller.

Mesaj teslim edildi demek iş tamamlandı demek değildir

RabbitMQ tarafındaki temel gerçek, bir mesajın birden fazla kez işlenebilmesidir. Consumer işlemi tamamlayıp veritabanına yazdıktan sonra acknowledgment broker'a ulaşmadan bağlantı kesilirse mesaj yeniden teslim edilebilir. Bu nedenle finansal kayıt, stok düşümü veya e-posta gönderimi gibi etkiler için “consumer bir kere çalışır” varsayımı güvenli değildir.

Örneğin OrderCreated event'ini alan Inventory.Worker rolünü düşünün. Worker mesajı alır, orders tablosundaki sipariş kimliğine göre rezervasyon kaydı oluşturur ve ancak yerel işlem başarıyla tamamlandığında ack gönderir. Aynı mesaj tekrar gelirse consumer, message ID veya iş açısından doğal olan benzersiz anahtar üzerinden işlemin daha önce uygulanıp uygulanmadığını kontrol eder.

Publisher tarafında benzer bir boşluk vardır. Orders.Api, OrdersDbContext ile siparişi kaydedip hemen ardından RabbitMQ'ya event gönderirse veritabanı commit'i başarılı, publish çağrısı başarısız olabilir. Sipariş vardır ama diğer servislerin bundan haberi yoktur.

Transactional outbox bu iki adımı tek yerel veritabanı işlemi içine alır: sipariş ve gönderilecek event kaydı birlikte yazılır. Ayrı bir background worker outbox kayıtlarını RabbitMQ'ya yollar ve publisher confirm aldıktan sonra gönderildi olarak işaretler. Bu yöntem broker ile veritabanı arasında dağıtık transaction kurmaya çalışmadan başarısızlık penceresini yönetilebilir hale getirir.

Retry politikasını da consumer kodundaki sınırsız bir döngüye bırakmayın. Ağ kesintisi gibi geçici bir hata tekrar denenebilir; geçersiz payload veya karşılanamayacak bir iş kuralı aynı mesajı sürekli döndürmemelidir. Sınırlı retry sonrasında ayrı bir dead-letter queue, başarısız mesajı inceleme ve kontrollü yeniden işleme imkânı verir.

Ölçekleme queue sayısından başlamaz

Bir queue'ya birden fazla .NET worker bağlamak, RabbitMQ'nun competing consumers modeliyle işi instance'lar arasında dağıtır. CPU veya I/O yükü arttığında consumer sayısını yükseltmek işe yarayabilir, fakat ordering gereksinimi varsa paralellik aynı anahtara ait mesajların beklenen sırada uygulanmasını bozabilir.

Prefetch de kapasite ayarıdır, sihirli bir performans düğmesi değildir. Çok yüksek değer bir consumer'ın çok sayıda mesajı üzerinde tutmasına ve iş dağılımının dengesizleşmesine yol açabilir; çok düşük değer ise hızlı consumer'larda broker ile gereksiz bekleme yaratabilir. Değeri mesaj işleme süresi, consumer concurrency'si ve gözlenen kuyruk davranışı üzerinden ayarlayın.

Operasyon toplantısında yalnızca queue uzunluğuna bakmak da eksik kalır. Unacked mesajlar, mesaj yaşı, publish ve consume hızı, dead-letter birikimi ve consumer hataları birlikte incelendiğinde darboğazın producer, broker veya consumer tarafında olduğu daha net anlaşılır.

Karar: Event için RabbitMQ, güvenilirlik için uygulama tasarımı

Servis başka bir servisin anlık sonucuna ihtiyaç duyuyorsa sırf asenkron görünmek için RabbitMQ eklemeyin. İşlem bağımsız devam edebiliyor ve birden fazla consumer gerçekleşmiş bir olaya kendi hızında tepki verebiliyorsa event yayınlamak daha temiz bir sınır oluşturur.

Yeni bir .NET akışında RabbitMQ seçtiğimde minimum tasarım çizgim nettir: kalıcı mesaj sözleşmesi, publisher confirm, consumer acknowledgment, idempotent işleme, sınırlı retry ve dead-letter davranışı. Veritabanı değişikliği ile event yayını aynı iş kararının parçalarıysa outbox da bu çizgiye girer.

Pazartesi yapılacak karar RabbitMQ'nun hangi exchange tipini desteklediği değil, OrderCreated mesajının gerçekten bir event olup olmadığıdır. O sınırı doğru kurduktan sonra queue ve worker ölçeklemek mekanik bir probleme dönüşür; sınırı yanlış kurarsanız broker sadece bağımlılığı daha zor görülen hale getirir.

yorumlar

0

Henüz yorum yok. İlk notu sen bırak.

Yorum yazmak için giriş yap.

Gmail ile saniyeler içinde, ya da e-posta ile kaydol.

bağlı 26109:22:58