RRabbitMQ Handbook

ORTA

Dead Letter Exchange & Retry Patterns

Bir mesaj işlenemediğinde ne olur? Kaybolmasın istiyorsan bir "çöp değil, tekrar deneme" mekanizması lazım. Dead Letter Exchange (DLX) tam bunu yapar: başarısız mesajları ayrı bir queue'ya yönlendirir — oradan tekrar denenebilir, incelenebilir veya loglanabilir.

Kod örneği görünümü Bu sayfadaki eşleşen örnekleri seçilen istemciye göre gösterir.

DOĞRULANMAMIŞ ÖZELLİK: Bu bölümdeki Native Delayed Retry policy key'leri (delayed-retry-type, delayed-retry-min, delayed-retry-max) RabbitMQ 4.3 release notes'tan alınmıştır ancak resmi dokümantasyonda henüz doğrulanamamıştır. Production'da kullanmadan önce rabbitmqctl list_policies ile key'lerin geçerli olduğunu mutlaka test edin. Eski sürümlerde bu key'ler sessizce ignore edilir — hata vermez ama retry çalışmaz.

Basit analoji: Postane bir mektubu teslim edemezse çöpe atmaz — "iade" damgası vurup gönderene veya özel bir dolaba koyar. DLX = o iade mekanizması.

Mesaj ne zaman "dead letter" olur: reddedildiğinde (nack/reject), süresi dolduğunda (TTL) veya queue dolduğunda (limit aşımı). RabbitMQ 4.3 ile gelen native Delayed Retry özelliği, eski workaround'lara olan ihtiyacı azaltır.

Main Queue payment-processing Consumer process() ✓ Ack Mesaj silindi Delayed Retry delay = min × delivery_count 🆕 RabbitMQ 4.3 native DLX Queue delivery-limit aşıldı Dead Letter Store Manuel inceleme / alert success transient fail permanent / limit retry

DLX Tetiklenme Koşulları

Koşul Açıklama Gerçek Hayat
basic.reject / basic.nack (requeue=false) Consumer mesajı işleyemedi Geçersiz format, business rule violation
Message TTL expired x-message-ttl süresi doldu 24 saat içinde işlenmeyen sipariş
Queue length limit exceeded x-max-length veya x-max-length-bytes Queue overflow koruması
Delivery limit exceeded x-delivery-limit (Quorum queue, default: 20) Poison message koruması

Delayed Retry: Eski vs Yeni

Özellik Eski Yöntem (TTL + DLX loop) RabbitMQ 4.3 Native Delayed Retry
Kurulum Retry queue + DLX binding + TTL per queue Tek policy: delayed-retry-type
Backoff Sabit (queue başına sabit TTL) Linear: min_delay × delivery_count
Max delay Queue sayısı kadar farklı TTL gerekir delayed-retry-max ile cap
Queue overhead Her retry seviyesi için ayrı queue Tek queue, internal deferred state
Gözlenebilirlik Zayıf (hangi retry'da belirsiz) Management UI'da deferred count görünür

Gerçek hayat senaryosu: E-ticaret stok servisi: Payment confirmation geldi ama inventory API geçici olarak down. Consumer nack gönderir, delayed retry devreye girer: 1. deneme 1sn, 2. deneme 2sn, 3. deneme 3sn... max 30sn'ye kadar. 5 başarısız delivery sonrası mesaj DLX'e düşer ve ops team alert alır.

# ⚠️ DOĞRULANMAMIŞ: Bu policy key'leri RabbitMQ 4.3 release notes'tan alınmıştır.
# Production'da önce test ortamında doğrulayın: rabbitmqctl list_policies
# Çalışmazsa aşağıdaki .NET DLX+TTL pattern'ini kullanın (doğrulanmış).
#
# Delayed retry policy: tüm "order." queue'larına uygula
rabbitmqctl set_policy order-retry     "^order."     '{"delayed-retry-type":"all","delayed-retry-min":1000,"delayed-retry-max":30000,"delivery-limit":5,"dead-letter-exchange":"dlx.main"}'     --priority 10     --apply-to "quorum_queues"

# Sonuç:
# - İlk retry: 1000ms
# - İkinci retry: 2000ms
# - Üçüncü retry: 3000ms
# - ... (capped at 30000ms)
# - 5. delivery-count aşılırsa → dlx.main exchange'e dead-letter
// 1. DLX Exchange
await channel.ExchangeDeclareAsync("dlx.main", ExchangeType.Direct, durable: true);

// 2. Dead letter queue (manual review)
await channel.QueueDeclareAsync("dead-letters", durable: true, exclusive: false, autoDelete: false,
    arguments: new Dictionary<string, object?>
    {
        ["x-queue-type"] = "quorum",
        ["x-message-ttl"] = 604_800_000  // 7 gün retention sonra sil
    });
await channel.QueueBindAsync("dead-letters", "dlx.main", routingKey: "#");

// 3. Main queue — DLX bağlantılı
await channel.QueueDeclareAsync("order-processing", durable: true, exclusive: false, autoDelete: false,
    arguments: new Dictionary<string, object?>
    {
        ["x-queue-type"] = "quorum",
        ["x-dead-letter-exchange"] = "dlx.main",
        ["x-dead-letter-routing-key"] = "order.failed",
        ["x-delivery-limit"] = 5
    });

at-least-once DLX (Quorum Queue): dead-letter-strategy: at-least-once aktifleştirildiğinde, DLX target queue confirm gönderene kadar mesaj source queue'da tutulur. Bu daha güvenlidir ama overflow: reject-publish zorunludur (drop-head ile çalışmaz).