Message Queue Sistemleri: Servisler Arasında Güvenilir Veri Akışı

Modern uygulamalarda servislerin birbirini doğrudan ve anında çağırması ilk bakışta pratik görünür. Ancak trafik arttığında, bir servis bakımdayken veya anlık hata yaşadığında bu sıkı bağlantı zincirleme sorunlara dönüşür. Message Queue (mesaj kuyruğu) sistemleri, servisler arasına dayanıklı bir posta merkezi koyarak veriyi zamandan bağımsız ve güvenli biçimde taşır.

message-queue-sistemleri-50

``

Temel fikir basittir: producer bir mesaj üretir, mesajı kuyruk ya da topic’e gönderir; consumer ise uygun olduğunda bu mesajı işler. Producer’ın consumer’ın ayakta olup olmadığını bilmesine gerek kalmaz. Böylece sistemdeki zamansal bağımlılık azalır. Örneğin sipariş servisi, ödeme tamamlandığında e-posta servisini doğrudan çağırmak yerine order.paid olayını yayınlayabilir.

Bu yaklaşımın teorik temeli, asenkron iletişim ve gevşek bağlılık kavramlarıdır. Doğrudan HTTP iletişiminde gecikme yaklaşık olarak çağrı zincirindeki sürelerin toplamıdır:

\[T_{toplam} = T_{sipariş} + T_{ödeme} + T_{bildirim}\]

Kuyruklu mimaride sipariş servisi mesajı teslim ettikten sonra kendi işini bitirebilir. Bildirim işlemi daha sonra gerçekleşir. Kullanıcının gördüğü kritik yanıt süresi ise kabaca $T_{sipariş} + T_{mesaj_yayınlama}$ seviyesine iner.

Özellik Senkron HTTP Çağrısı Message Queue
Bağımlılık Servisler aynı anda çalışmalı Consumer daha sonra çalışabilir
Hata etkisi Hata çağrı zincirini kesebilir Mesaj yeniden denenebilir
Ölçekleme Her çağrı anlık kapasite ister Consumer sayısı artırılabilir
Uygun kullanım Anlık sorgular Olaylar ve uzun süren işler

Güvenilirlik denildiğinde üç teslim garantisi öne çıkar. At-most-once mesajı en fazla bir kez işler; hızlıdır ama kayıp riski taşır. At-least-once mesajın kaybolmamasını hedefler, fakat aynı mesaj tekrar gelebilir. Exactly-once ise ideal görünse de dağıtık sistemlerde maliyetli ve karmaşıktır. Pratikte en yaygın reçete, at-least-once teslimat ile idempotent consumer tasarlamaktır. Yani aynı mesaj iki kez işlense bile sonuç değişmemelidir.

Teslim Modeli Mesaj Kaybı Tekrar İşleme Tipik Strateji
At-most-once Mümkün Beklenmez Telemetri, önemsiz loglar
At-least-once Çok düşük Mümkün Sipariş, ödeme olayları
Exactly-once Hedeflenir Hedeflenmez Yüksek maliyetli özel senaryolar

Aşağıdaki Python örneği, RabbitMQ ile kalıcı bir sipariş mesajı yayınlar. delivery_mode=2, broker yeniden başlasa bile mesajın kalıcı olmasına yardımcı olur; gerçek dayanıklılık için kuyruk da durable tanımlanmalıdır.

import json
import pika

connection = pika.BlockingConnection(
    pika.ConnectionParameters("localhost")
)
channel = connection.channel()
channel.queue_declare(queue="orders", durable=True)

order = {"eventId": "evt-42", "orderId": 901, "total": 349.90}
channel.basic_publish(
    exchange="",
    routing_key="orders",
    body=json.dumps(order),
    properties=pika.BasicProperties(delivery_mode=2)
)
connection.close()

Consumer tarafında mesaj işlendikten sonra onay (ack) vermek kritik bir ayrıntıdır. İşlem sırasında uygulama çökerse broker, onaylanmamış mesajı tekrar dağıtabilir. Bu nedenle consumer, eventId gibi benzersiz bir kimliği veritabanında takip ederek yinelenen olayları atlamalıdır. Başarısız mesajlar için sınırsız tekrar denemek yerine retry queue, artan bekleme süresi ve dead-letter queue (DLQ) kullanılmalıdır. DLQ, zehirli mesajları ana akışı durdurmadan incelemeye alır.

RabbitMQ genellikle görev kuyrukları ve karmaşık yönlendirme için; Kafka ise yüksek hacimli olay akışları, kayıtların tekrar okunması ve analitik senaryoları için tercih edilir. Araç seçimi moda göre değil; sıralama ihtiyacı, mesaj hacmi, saklama süresi ve tüketici modeline göre yapılmalıdır. Doğru tasarlanmış bir kuyruk, servislerin arasındaki trafiği yalnızca taşımakla kalmaz; sistemin zor günlerde de sakin kalmasını sağlar.

Yorumlar