Никогда больше не теряйте сообщения и сократите время устранения неполадок с помощью событий с трассировкой в реальном времени Memphis.dev
Вам когда-нибудь звонили посреди ночи и говорили: «Инфраструктура выглядит нормально, но какой-то сервис не потребляет данные / сообщения доставляются повторно. Пожалуйста, разберитесь с этим».
Повторно доставленные сообщения также называются «отравленными сообщениями».
Отравленные сообщения = сообщения, которые заставляют потребителя неоднократно требовать доставки (возможно, из-за сбоя потребителя) таким образом, что сообщение никогда не обрабатывается полностью и не подтверждается, чтобы его можно было прекратить повторно отправлять тому же потребителю.
Пример: Некоторое сообщение в произвольной очереди подталкивается/вытаскивается потребителю или потребителем. Этот потребитель по какой-то причине не может его обработать. Это может быть связано с ошибкой, неизвестной схемой, проблемой с ресурсами и т.д..
В RabbitMQ, например, очереди кворума отслеживают количество неудачных попыток доставки и отображают его в заголовке «x-delivery-count», который включается в любое повторно доставленное сообщение. Можно установить предел доставки для очереди с помощью аргумента политики, delivery-limit. Если сообщение было возвращено большее количество раз, чем установлено лимитом, оно будет отброшено или отправлено в мертвую очередь (если настроен DLX).
Любому разработчику, использующему очередь / шину обмена сообщениями, известно, что о ядовитых сообщениях следует позаботиться, и ответственность за это лежит на разработчике.
В RabbitMQ наиболее распространенным и простым решением является включение DLX (dead-lettered queue), но на этом все не заканчивается.
Восстановление отравленного сообщения — это только первая часть, разработчик также должен понять, что вызывает такое поведение, и устранить проблему.
Решения
Хотя существует классическое решение — зафиксировать/признать сообщение как можно скорее, это не лучший вариант для случаев, когда требуется, чтобы сообщения подтверждались только после завершения обработки.
Другие подходы —
Как обрабатывать непризнанные сообщения в RabbitMQ
- Включите DLX
- Настройте DLX
- Разместите ключ маршрутизации
- Создайте выделенный потребитель, указанный на DLX
- Потреблять непринятые сообщения
- Исправьте код/события
Как обрабатывать непринятые сообщения в Apache Kafka
Не существует готового способа повторной доставки/восстановления таких сообщений.
-
Убедитесь, что в коде есть журналы, отслеживающие исключения, и экспорт в pagerduty/datadog/new relic/etc….
-
Если срок хранения сообщения слишком мал, оно исчезнет до того, как разработчик получит возможность его отладить. В большинстве случаев сообщение не будет уникальным и может потеряться, но в других, таких как транзакции/атомарные запросы, это так. Чтобы смягчить это, необходимо сделать обертку, обеспечивающую эту функциональность. Отличным примером такой обертки, обеспечивающей такую возможность и даже больше, является GreyHound https://github.com/wix/greyhound от Wix. Определенно стоит взглянуть.
-
Существуют и другие примеры использования, в которых для сохранения сообщения в процессе обработки перед фиксацией используется некий кэш DB.
Непризнанные сообщения в Memphis.dev
Когда мы начали уточнять наш подход, понимать потребности, проверять опыт и создавать ценность, которую он принесет нашим пользователям, три ключевые задачи руководили нашим процессом — это
- Точка входа пользователя в проблему.
- Быстрое понимание проблемного потребителя и первопричины проблемы.
- Код исправляется. Разработчик должен отладить исправление с помощью аналогичного сообщения, чтобы убедиться, что оно работает.
1 — Определите триггер
В брокере Memphis на уровне SDK мы используем параметр под названием «maxMsgDeliveries».
При достижении этого порога брокер не будет повторно отправлять сообщение «failed-to-ack» одной и той же группе потребителей.
2 — Уведомление
- Брокер Memphis фиксирует событие пересечения «maxMsgDeliveries = 2» для каждой станции, для каждой группы потребителей.
- Сохраняет время_отправки и полезную нагрузку повторно доставленного сообщения в файловом хранилище Memphis в течение 3 часов.
- Пометьте сообщение как отравленное определенным потребителем.
- Создайте предупреждение.
3 — Определите группу потребителей, которая не подтвердила сообщение.
Вместо того чтобы просматривать журналы и многочисленные группы потребителей, мы хотели сузить поиск до минимума, поэтому простое нажатие на «трассировку в реальном времени» приведет к появлению экрана с графиком, показывающим КУ, которые прошли порог повторной доставки.
4 — Исправление и отладка
После того, как разработчик поймет, что пошло не так, и создаст исправление, прежде чем вводить код, который приведет к возможно большему количеству корректировок при поступлении новых сообщений, мы создали механизм «Resend», который будет отправлять непринятое сообщение столько раз, сколько необходимо (до ACK) группе потребителей, которая не смогла подтвердить сообщение в первый раз.
Непризнанное сообщение будет извлекаться из внутренней БД Memphis, попадать в специальную станцию для каждой станции, для каждого CG, и только по запросу. Затем оно будет передано непризнанному CG — БЕЗ ИЗМЕНЕНИЯ КОДА, с использованием того же самого уже настроенного emit.
Вот и все. Не нужно создавать процесс персистентности, кэш-базу данных, DLQ или массовую логику. Вы можете быть уверены, что ни одно сообщение не будет потеряно.
Все еще в процессе разработки, но если вам интересно — sandbox.memphis.dev
Автор этой статьи — Авраам Нееман