Ответ
В проектах с микросервисной архитектурой на PHP мы обеспечивали отказоустойчивость RabbitMQ через комбинацию подходов.
1. Гарантированная доставка и обработка:
Использовали подтверждение (ack/nack) и ручной режим подтверждения (basic_consume с auto_ack = false). Это позволяло повторно ставить в очередь сообщения при сбоях в обработчике.
$channel->basic_consume(
'order_queue',
'',
false, // auto_ack = false
false,
false,
false,
function (AMQPMessage $msg) {
try {
// Бизнес-логика обработки заказа
$this->orderService->process($msg->body);
// Явное подтверждение успешной обработки
$msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
} catch (Exception $e) {
// При ошибке — отрицательное подтверждение с requeue = true
$msg->delivery_info['channel']->basic_nack($msg->delivery_info['delivery_tag'], false, true);
// Логировали ошибку в Sentry
}
}
);
2. Зеркалирование (Mirrored) очередей: Настраивали политики HA для критичных очередей, чтобы они реплицировались на несколько узлов кластера. Это защищало от потери сообщений при падении одного брокера.
3. Dead Letter Exchange (DLX) для проблемных сообщений: Сообщения, которые не удалось обработать после N попыток, отправлялись в DLX, а оттуда — в очередь-«кладбище» для ручного разбора. Это предотвращало засорение основной очереди битыми сообщениями.
4. Устойчивость подключений: В клиентском коде реализовывали логику повторного подключения с экспоненциальной задержкой и heartbeat'ами, чтобы пережить кратковременные сетевые сбои или рестарт брокера.
5. Мониторинг: Отслеживали длину очередей, скорость потребления и статус соединений через API управления RabbitMQ, интегрируя метрики в Prometheus и настраивая алерты в Grafana при достижении порогов.