Расскажи про свой опыт работы с RabbitMQ

«Расскажи про свой опыт работы с RabbitMQ» — вопрос из категории Архитектура, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Я использовал RabbitMQ в нескольких проектах на PHP (Symfony/Laravel) для построения асинхронной, отказоустойчивой коммуникации между сервисами.

Основные сценарии:

  • Фоновая обработка задач: отправка email, генерация PDF-отчетов, обработка загруженных файлов. Задачи помещались в очередь, а воркеры (обычно Symfony Console-команды или Laravel Queues с драйвером rabbitmq) обрабатывали их независимо от основного HTTP-запроса.
  • Событийная архитектура (Event-Driven): при изменении сущности в одном микросервисе (например, «Заказ создан») публиковалось событие в RabbitMQ. Другие сервисы (сервис уведомлений, сервис аналитики) подписывались на это событие и реагировали, не создавая прямых жестких зависимостей.
  • Балансировка нагрузки: несколько экземпляров воркеров подписывались на одну очередь, и RabbitMQ распределял сообщения между ними по принципу round-robin.

С чем работал и пример кода (PHP с библиотекой php-amqplib):

// Публикация сообщения с персистентностью
$connection = new AMQPStreamConnection('rabbitmq-host', 5672, 'user', 'pass');
$channel = $connection->channel();

// Объявление очереди (durable=true для сохранения при перезагрузке брокера)
$channel->queue_declare('order_processing', false, true, false, false);

$messageBody = json_encode(['order_id' => 123, 'action' => 'created']);
$msg = new AMQPMessage($messageBody, [
    'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT
]);

$channel->basic_publish($msg, '', 'order_processing');
$channel->close();
$connection->close();

Продвинутые практики:

  • Dead Letter Exchanges (DLX): Настраивал для перемещения «отравленных» сообщений (которые не удалось обработать после N попыток) в отдельную очередь для анализа.
  • TTL (Time-To-Live): Использовал для сообщений с ограниченным сроком актуальности (например, коды подтверждения).
  • Подтверждения (Acknowledgements): Всегда включал $channel->basic_ack() в воркерах после успешной обработки, чтобы избежать потери сообщений.
  • Кластеризация: На production-окружении разворачивал кластер RabbitMQ (как минимум два узла) с зеркалированием очередей для обеспечения высокой доступности.