Dead Letter Queue. Как обрабатывать битые сообщения в RabbitMQ и Kafka
Очереди сообщений помогают строить отказоустойчивые распределённые системы. Однако в любой системе рано или поздно появляются сообщения, которые невозможно обработать.
Например:
- некорректный JSON
- удалённый пользователь, на которого ссылается событие
- ошибка бизнес-логики
- несовместимость версий сервисов
- временно недоступная база данных
Если такие сообщения обрабатывать неправильно, они могут блокировать очередь, создавать бесконечные ретраи или приводить к потере данных.
Для решения этой проблемы используются Dead Letter Queue (DLQ).
Что такое Dead Letter Queue
Dead Letter Queue — это специальная очередь для сообщений, которые не удалось успешно обработать.
Вместо того чтобы бесконечно пытаться обработать проблемное сообщение, система переносит его в отдельное хранилище для дальнейшего анализа.
Схема выглядит примерно так:
Producer
↓
Main Queue
↓
Consumer
↓
Ошибка
↓
Dead Letter QueueОсновная очередь продолжает работать, а проблемные сообщения не мешают обработке остальных данных.
Почему нельзя просто повторять обработку бесконечно
На первый взгляд кажется логичным постоянно выполнять retry.
Но на практике это быстро приводит к проблемам.
Представим сообщение:
{
"userId": 123,
"email": "invalid-email"
}Если код обработки всегда падает на этом сообщении, повторная попытка ничего не изменит.
В результате получаем:
Ошибка
Retry
Ошибка
Retry
Ошибка
Retry
...Такое сообщение может годами крутиться в очереди, создавая нагрузку и засоряя логи.
Поэтому обычно задают максимальное количество попыток обработки.
После превышения лимита сообщение отправляется в DLQ.
Какие ошибки стоит отправлять в DLQ
Не каждая ошибка должна приводить к попаданию сообщения в dead letter queue.
Полезно разделять ошибки на две категории.
Временные ошибки:
- недоступность БД
- сетевые проблемы
- перегрузка сервиса
- временный timeout
Для таких случаев retry обычно помогает.
Постоянные ошибки:
- битый JSON
- отсутствующее обязательное поле
- нарушение схемы данных
- ошибка бизнес-валидации
Здесь повторная обработка бессмысленна.
Именно такие сообщения чаще всего оказываются в DLQ.
Как работает DLQ в RabbitMQ
В RabbitMQ механизм реализован через Dead Letter Exchange.
Основная очередь настраивается так, чтобы отклонённые сообщения автоматически перенаправлялись в специальную очередь.
Упрощённая схема:
Main Queue
↓
Reject
↓
Dead Letter Exchange
↓
Dead Letter QueueСообщение может попасть туда по нескольким причинам:
- consumer сделал reject
- превышен TTL
- превышен лимит длины очереди
- сообщение несколько раз не прошло обработку
После этого его можно анализировать отдельно от основного потока.
Как работает DLQ в Kafka
В Kafka отдельного встроенного механизма DLQ нет.
Обычно создаётся специальный топик:
orders
orders-dlqЕсли consumer не смог обработать событие после нескольких попыток, он публикует его в DLQ-топик.
При этом обычно сохраняют:
- исходное сообщение
- текст ошибки
- стек исключения
- время возникновения проблемы
Это значительно упрощает расследование инцидентов.
Что хранить в DLQ
Частая ошибка — складывать только исходное сообщение.
Через несколько дней разобраться в причине становится сложно.
Полезно сохранять дополнительные данные:
{
"payload": {...},
"error": "Validation failed",
"service": "billing",
"attempts": 5,
"timestamp": "2026-06-03T12:00:00Z"
}Так инженеры сразу понимают, что произошло и где искать проблему.
Нужно ли мониторить DLQ
Обязательно.
Само существование DLQ не решает проблему.
Если никто не следит за содержимым очереди, сообщения просто будут накапливаться.
Поэтому обычно отслеживают:
- количество сообщений в DLQ
- скорость роста DLQ
- число новых сообщений за период
- самые частые ошибки
- возраст старейшего сообщения
Резкий рост DLQ часто становится первым признаком проблем после релиза.
Что делать с сообщениями из DLQ
После попадания в DLQ есть несколько вариантов.
Первый — исправить данные и повторно отправить сообщение в основную очередь.
Второй — исправить ошибку в коде и выполнить replay всех сообщений.
Третий — признать данные некорректными и удалить их.
Выбор зависит от характера проблемы и требований бизнеса.
Опасность автоматического replay
Многие команды делают кнопку «Вернуть всё обратно в очередь».
Это удобно, но опасно.
Если причина ошибки не устранена, происходит следующее:
Main Queue
↓
DLQ
↓
Replay
↓
Main Queue
↓
DLQПолучается бесконечный цикл.
Поэтому replay должен выполняться только после анализа причины сбоя.
Типичные причины роста DLQ
На практике чаще всего встречаются:
- изменение схемы сообщений
- ошибки сериализации
- несовместимость версий сервисов
- баги после релиза
- удалённые данные в БД
- ошибки миграций
Во многих случаях всплеск DLQ позволяет обнаружить проблему раньше, чем пользователи начнут массово жаловаться.
Хорошие практики работы с DLQ
Полезно придерживаться нескольких правил:
- ограничивать число retry
- сохранять информацию об ошибке
- мониторить размер DLQ
- настраивать алерты на рост сообщений
- регулярно анализировать содержимое очереди
- иметь безопасный механизм replay
DLQ должна рассматриваться как инструмент диагностики, а не как место для бесконечного хранения проблемных событий.
Итоги
Dead Letter Queue позволяет изолировать сообщения, которые невозможно успешно обработать.
Без DLQ битые события способны создавать бесконечные ретраи, перегружать систему и мешать обработке нормальных данных.
В RabbitMQ для этого используется Dead Letter Exchange, а в Kafka обычно создают отдельный DLQ-топик.
Грамотно настроенная DLQ помогает быстро находить ошибки интеграции, безопасно обрабатывать сбои и поддерживать стабильность распределённой системы даже при появлении некорректных сообщений.
Настроить мониторинг за 30 секунд
Надежные оповещения о даунтаймах. Без ложных срабатываний