ویرگول
ورودثبت نام
فرهاد صادقی
فرهاد صادقیمهندس نرم افزار، طراحی و راه اندازی سیستم های نرم افزاری بر پایه معماری میکروسرویس
فرهاد صادقی
فرهاد صادقی
خواندن ۲ دقیقه·۱۲ روز پیش

پیام‌های ناموفق و Retry در RabbitMQ

✅ مشاهده پیام‌های ناموفق در RabbitMQ

❌ واقعیت مهم

RabbitMQ به‌صورت پیش‌فرض جایی برای دیدن پیام‌های ناموفق نداره.
اگر پیام fail بشه و درست هندل نشه، ممکنه برای همیشه حذف بشه.


✔ راه‌حل استاندارد: Dead Letter Queue (DLQ)

پیام چه زمانی می‌ره DLQ؟

  • reject یا nack با requeue=false

  • اتمام TTL

  • پر شدن صف (max-length)


🔧 تنظیم DLQ روی صف اصلی

x-dead-letter-exchange: my.dlx x-dead-letter-routing-key: dead

🔍 چطور پیام‌های ناموفق رو ببینیم؟

  1. فعال بودن RabbitMQ Management Plugin

  2. رفتن به UI → Queues

  3. باز کردن DLQ

  4. دکمه Get Messages

📌 مناسب دیباگ و بررسی، نه مصرف دائمی


📎 اطلاعات مهم داخل پیام DLQ

در headerها:

  • x-death.reason (علت fail)

  • x-death.count (چند بار fail شده)

  • x-death.exchange

  • x-death.queue


اگر DLQ درست مدیریت نشه، می‌تونه حافظه یا دیسک سرور RabbitMQ رو پر کنه و باعث down شدن سرور بشه.
ولی خبر خوب اینه که با چند تا تنظیم ساده، این ریسک تقریباً صفر می‌شه 👇

چرا DLQ خطرناک می‌شه؟

DLQ دقیقاً مثل هر صف دیگه‌ایه. اگر:

  • پیام‌ها دائماً fail بشن

  • مصرف‌کننده‌ای برای DLQ نداشته باشی

  • یا limit نذاری

اون صف بی‌نهایت رشد می‌کنه.

نتیجه:

  • اگر پیام‌ها transient باشن → RAM پر می‌شه

  • اگر persistent باشن → Disk پر می‌شه

  • RabbitMQ وقتی به limit برسه:

    • شروع به block کردن publisher می‌کنه

    • یا بدتر: کل node از دسترس خارج می‌شه ❌


چطور DLQ رو امن کنیم؟ (Best Practices)

1️⃣ حتماً برای DLQ محدودیت بذار (خیلی مهم)

x-max-length: 10000 x-overflow: drop-head

یا بر اساس حجم:

x-max-length-bytes: 100MB

📌 این باعث می‌شه پیام‌های خیلی قدیمی حذف بشن.

2️⃣ روی DLQ هم TTL بذار

x-message-ttl: 604800000

مثلاً بعد از ۷ روز خودکار پاک بشن.

3️⃣ پیام‌های DLQ رو persistent نکن (در صورت امکان)

اگر فقط برای debug هست:

delivery_mode = 1 // transient

4️⃣ حتماً alarm های RabbitMQ رو مانیتور کن

RabbitMQ وقتی منابع کم می‌شن alarm می‌زنه:

  • memory_alarm

  • disk_alarm

و publisher رو block می‌کنه.

حتماً این‌ها رو مانیتور کن:

rabbitmqctl status

یا در UI:

Overview → Node details

🔁 Retry در RabbitMQ (به روش درست)

DLQ برای retry نیست ❌

اشتباه رایج:

«بیایم پیام‌های DLQ رو دوباره publish کنیم»

❌ روش اشتباه

nack + requeue=true

این کار باعث loop و انفجار پیام می‌شه 💣
برای retry درست از:

  • Retry Queue

  • Delayed Exchange

  • یا backoff strategy

استفاده کن.

الگوی امن پیشنهادی

Main Queue ↓ fail Retry Queue (TTL + DLX) ↓ expire Main Queue ↓ fail after N tries DLQ (TTL + max-length)

🔧 Retry Queue

x-message-ttl: 30000 x-dead-letter-exchange: main.exchange

📌 پیام بعد از ۳۰ ثانیه دوباره به صف اصلی برمی‌گرده


🔢 محدود کردن retry

  • با header مثل x-retry-count

  • یا x-death.count

منطق:

retry < N → retry retry ≥ N → DLQ

⏳ Backoff (خیلی مهم)

چند retry queue با TTL مختلف:

  • retry 5s

  • retry 30s

  • retry 2m

🧠 چه پیام‌هایی retry بشن؟

✅ retry

  • timeout

  • network error

  • service unavailable

❌ چه پیام هایی مستقیم به DLQ می روند؟

  • validation error

  • business rule fail

  • message خراب


🔐 نکته حیاتی: Idempotency

Retry = احتمال پیام تکراری
consumer باید:

  • idempotent باشه

  • یا deduplication داشته باشه

rabbitmq
۱
۰
فرهاد صادقی
فرهاد صادقی
مهندس نرم افزار، طراحی و راه اندازی سیستم های نرم افزاری بر پایه معماری میکروسرویس
شاید از این پست‌ها خوشتان بیاید