RabbitMQ это message broker. В модели AMQP 0-9-1 producer публикует сообщение в exchange, exchange по bindings и routing key направляет его в одну или несколько queues, а consumer получает сообщение из queue. Consumer acknowledgement подтверждает обработку, publisher confirm подтверждает принятие сообщения broker. Для ошибок используют retry и dead-letter exchange.
Producer обычно не пишет напрямую в произвольную queue. Он публикует в exchange.
Exchange принимает сообщение и решает, куда его маршрутизировать.
Binding связывает exchange с queue.
Routing key участвует в выборе маршрута.
Queue хранит сообщения до доставки consumer.
Consumer обрабатывает сообщение и подтверждает результат.
Default exchange имеет пустое имя. Каждая queue автоматически связана с ним routing key, равным имени queue. Поэтому внешне это похоже на прямую публикацию в очередь.
Типы exchange
Тип
Правило
Direct
Точное совпадение routing key и binding key
Fanout
Копия сообщения во все связанные queues
Topic
Сопоставление routing key с шаблоном
Headers
Маршрутизация по headers
Для topic exchange обычно применяются шаблоны:
* заменяет одно слово;
# заменяет ноль или несколько слов.
Например, binding order.* совпадёт с order.created, но не с order.eu.created.
Ack, nack и requeue
При manual acknowledgement broker не удаляет доставленное сообщение, пока consumer не отправит ack.
Если consumer не может обработать сообщение:
nack/reject с requeue=true возвращает его в queue;
nack/reject с requeue=false отправляет его в DLX при наличии настройки или удаляет.
Бесконечный requeue является частым дефектом. Одно poison message может постоянно занимать consumer и создавать нагрузку.
Проверяй ограничение retries, задержку между попытками и конечный маршрут ошибки.
Publisher confirms и mandatory
Consumer ack и publisher confirm решают разные задачи.
Consumer ack сообщает broker, что consumer принял ответственность за обработку.
Publisher confirm сообщает publisher, что broker принял ответственность за публикацию.
Даже confirm не всегда доказывает, что сообщение попало хотя бы в одну queue. Для unroutable message publisher может использовать mandatory, чтобы получить возврат.
Надёжная публикация обычно требует:
подходящей durable queue и exchange;
persistent message;
publisher confirm;
обработки return при невозможности маршрутизации.
Один флаг persistent не создаёт полную гарантию.
Prefetch
Prefetch ограничивает количество неподтверждённых сообщений у consumer.
Слишком большой prefetch:
создаёт неравномерное распределение;
увеличивает объём повторной доставки после падения consumer;
повышает потребление памяти.
Слишком маленький prefetch:
ограничивает throughput;
заставляет consumer чаще ждать сеть.
Проверяй баланс на реальном времени обработки сообщений.
TTL и dead lettering
Сообщение может стать dead letter, если:
consumer отклонил его без requeue;
истёк TTL;
queue превысила лимит;
в некоторых типах queue произошли дополнительные условия доставки.
Dead Letter Exchange не является отдельным типом exchange. Это обычный exchange, настроенный как место перенаправления.
Проверки:
сохраняется ли причина ошибки;
не образуется ли цикл между queues;
можно ли безопасно повторить сообщение;
есть ли alert на рост DLQ;
не теряется ли оригинальный routing key;
кто и как очищает DLQ.
Durable, persistent и replicated
Эти понятия нельзя смешивать.
Durable queue переживает restart broker как сущность.
Persistent message помечено для устойчивого хранения.
Репликация queue защищает от отказа узла.
Для критичных сценариев RabbitMQ рекомендует рассматривать quorum queues. Но выбор типа queue зависит от требований к доступности, производительности и порядку.
Чек-лист тестирования RabbitMQ
Маршрутизация
правильный exchange;
правильный тип exchange;
корректный routing key;
все нужные bindings;
отсутствие неожиданных копий;
поведение unroutable message;
обязательный mandatory там, где потеря недопустима.
Обработка
ack только после завершения бизнес-операции;
nack при контролируемой ошибке;
ограниченный retry;
poison message не блокирует поток;
duplicate delivery не создаёт повторный эффект;
consumer восстанавливается после restart.
Сохранность
queue и exchange имеют ожидаемую durability;
сообщения persistent, если это требуется;
publisher confirm обрабатывается;
restart broker не теряет критичные сообщения;
проверена отказоустойчивость выбранного типа queue.
Нагрузка
длина queue;
скорость publish и consume;
unacked count;
memory и disk alarms;
время сообщения в queue;
prefetch;
поведение медленного consumer.
RabbitMQ и Kafka
Вопрос
RabbitMQ
Kafka
Базовая модель
Broker с exchanges и queues
Распределённый event log
Маршрутизация
Богатая маршрутизация через exchange
Producer выбирает topic и partition
После чтения
Сообщение удаляется после ack
Запись остаётся до retention
Повторное чтение истории
Обычно не основная модель
Естественная работа через offset
Порядок
Зависит от queue, consumers и requeue
Внутри одной partition
Типичные задачи
Команды, фоновые jobs, сложная маршрутизация
Потоки событий, replay, аналитика, интеграция
Это не таблица "кто лучше". Выбор зависит от задачи.
Вопросы на собеседовании
Чем exchange отличается от queue?
Exchange маршрутизирует, queue хранит сообщения для consumers.
Когда сообщение удаляется из queue?
При manual ack после подтверждения consumer. При auto ack ответственность считается переданной раньше, что повышает риск потери при сбое consumer.
Что такое DLQ?
Queue, куда через Dead Letter Exchange попадают сообщения, которые не удалось обработать или срок которых истёк.
Чем publisher confirm отличается от consumer ack?
Confirm относится к пути publisher -> broker. Ack относится к пути broker -> consumer и обработке сообщения.
Почему сообщения дублируются?
Consumer мог завершить операцию, но упасть до ack. Broker доставит сообщение снова. Поэтому обработчик должен быть идемпотентным.
Что будет без binding?
Exchange может не направить сообщение ни в одну queue. В зависимости от параметров оно будет возвращено publisher или отброшено.
Главное запомнить
Producer публикует в exchange.
Binding и routing key определяют queue.
Ack и confirm находятся на разных участках пути.
Requeue без лимита способен создать бесконечный цикл.
Persistent message без durable topology и confirm недостаточно.
Метрики ready, unacked и processing time помогают найти узкое место.