Что происходит между продюсером и консьюмером в RabbitMQ
Что проверяют
Понимаете ли вы, что сообщение идёт не напрямую от продюсера к консьюмеру, а через обменник, привязку и очередь, и что делать с сообщением, когда обработка упала. Для Python добавляется вопрос, знаете ли вы поведение клиента.
Как отвечать
Путь сообщения:
- продюсер публикует в обменник с ключом маршрутизации, в очередь напрямую он не пишет. Пустое имя обменника это обменник по умолчанию, который кладёт сообщение в очередь с именем, равным ключу;
- обменник по своему типу (
direct,topic,fanout,headers) и привязкам решает, в какие очереди попадут копии. Подходящих нет, значит сообщение исчезает молча, а флагmandatoryзаставляет брокер вернуть его отправителю; - очередь хранит сообщение до выдачи. Долговечная очередь и постоянный режим доставки нужны, чтобы пережить перезапуск брокера;
- консьюмер подписывается, брокер отдаёт сообщения пачкой размером
prefetch_count; - после обработки идёт подтверждение, отказ с возвратом в очередь или отказ без возврата, и тогда работает обменник мёртвых сообщений.
Добавьте про гарантии: подтверждения публикации на стороне продюсера, ручные подтверждения на стороне консьюмера, доставка как минимум один раз. Отсюда требование к обработчику: он должен быть идемпотентным по ключу из сообщения.
Про Python скажите, что соединение в pika не потокобезопасно, подтверждать нужно из потока цикла событий, а для асинхронного кода есть aio-pika.
Где спотыкаются
Включают автоматическое подтверждение. Сообщение считается доставленным в момент выдачи, и падение обработчика уносит его насовсем, причём пропажа обнаруживается не в логах, а по расхождению данных.
Второе: держат тяжёлую обработку прямо в колбэке и блокируют цикл. Контрольные пакеты соединения не уходят, брокер рвёт подключение и выдаёт сообщение заново. Снаружи это выглядит как дубликаты операций без единой ошибки в логе.
Третье: возвращают неудачное сообщение в ту же очередь без счётчика попыток. Испорченное сообщение крутится по кругу и занимает консьюмера. Нужен предел попыток и отдельная очередь для разбора.