Retry, TTL, dead lettering và replay
Retry là workflow có trạng thái, deadline và ownership. DLQ/parking queue là nơi điều tra và phục hồi có kiểm soát, không phải nơi vứt message rồi quên.
1. Dead-letter lifecycle
Message có thể dead-letter khi consumer reject/nack với requeue=false, message hết TTL, queue vượt length limit, hoặc quorum queue vượt delivery limit. Dead-letter exchange route lại theo configured exchange và optional routing key.
| Trigger | Ý nghĩa thường gặp | Điểm cần quyết định |
|---|---|---|
| Rejected | Consumer phân loại không xử lý được | Retry hay parking ngay |
| Expired | Delay bucket hoặc work đã quá hạn | Replay hay discard theo business TTL |
| Max length | Overload/capacity policy | Drop/dead-letter mode và alert |
| Delivery limit | Repeated redelivery/poison | Quarantine và root-cause |
RabbitMQ thêm lịch sử dead lettering trong headers như x-death, được nén theo queue/reason. Dùng metadata này để quan sát attempt nhưng đừng để application tùy ý sửa header hoặc tin nó như business idempotency key.
2. Retry topology và delay buckets
main queue
-- failure --> retry exchange
--> retry.5s / retry.30s / retry.5m queues
-- TTL expiry + DLX --> main exchange
-- attempts exhausted --> parking / DLQ
Một hoặc nhiều TTL queues tạo delayed retry mà không hot-loop main queue. Ghi stable message ID, attempt, first-failure time, reason class, trace/correlation ID và original route. Backoff exponential có jitter giúp tránh retry đồng loạt khi dependency hồi phục.
Per-message TTL trong cùng queue có thể bị giữ sau message chưa hết hạn ở đầu queue; nhiều delay buckets theo fixed policy thường predictable hơn. Plugin delayed-message là lựa chọn deployment riêng, cần đánh giá support/upgrade/failure semantics.
3. Requeue tức thời và retry storm
nack(requeue=true) có thể đưa delivery về vị trí gần đầu queue; nếu lỗi vẫn còn, consumer nhận lại ngay, đốt CPU/network, tăng redelivery và làm starve message khỏe. Prefetch lớn và nhiều consumers có thể biến vòng lặp thành broker-wide storm.
4. DLX policy và dead-letter safety
Ưu tiên policy cho dead-letter exchange/routing key vì có thể thay đổi mà không redeclare queue; hard-coded x-arguments cần delete/redeploy để đổi và dễ drift giữa services. Permission phải cho phép queue owner đọc source và write vào DLX khi declare.
Dead-lettering là internal republish và guarantee phụ thuộc queue/configuration. Target exchange/queue thiếu hoặc unavailable có thể làm message không đến nơi; quorum queues có tùy chọn at-least-once dead lettering với điều kiện cụ thể. Theo dõi dead-letter failures và không mặc định DLX là lossless.
Broker phát hiện một số dead-letter cycles và có thể drop message trong cycle không có rejection. Thiết kế routing graph acyclic, thêm terminal parking queue và test topology thay vì dựa vào cycle detection.
5. Safe replay workflow
Sửa root cause và xác nhận downstream capacity trước replay. Tool replay phải có filter theo reason/time/schema/tenant, dry-run count/sample, rate/concurrency limit, pause/abort, audit actor, stable identity và destination allowlist.
- Kiểm schema compatibility và decryptability của payload cũ.
- Giữ original event ID; tạo replay operation ID riêng để audit.
- Consumer phải idempotent vì original có thể đã commit side effect.
- Không xóa DLQ trước khi destination confirm và reconciliation hoàn tất.
- Canary một batch nhỏ rồi quan sát error/lag/downstream saturation.
6. Observability và recovery gates
Đo retry rate theo reason/attempt, age của message cũ nhất, dead-letter ingress/egress, parking depth, replay success/failure, requeue rate và main-queue latency. Alert theo tốc độ tăng và business age, không chỉ queue depth tuyệt đối.