Что происходит с сообщением в RabbitMQ, если оно не было доставлено потребителю?

«Что происходит с сообщением в RabbitMQ, если оно не было доставлено потребителю?» — вопрос из категории Брокеры сообщений, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Поведение зависит от подтверждения (acknowledgment) и настроек очереди.

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

  1. Без подтверждения (Ack): Если потребитель не отправил basicAck, сообщение остается в очереди и будет повторно доставлено (возможно, другому потребителю).

  2. С отрицательным подтверждением (Nack): Потребитель явно отправляет basicNack. Поведение зависит от флага requeue:

    • requeue=true — сообщение возвращается в исходную очередь.
    • requeue=false — сообщение удаляется (часто перенаправляется в Dead Letter Exchange, если он настроен).
  3. Dead Letter Exchange (DLX): Позволяет автоматически перенаправлять "мертвые" сообщения (недоставленные после N попыток, истекшие по TTL или явно отклоненные) в специальный обменник для дальнейшего анализа.

Пример обработки с Nack в Java:

channel.basicConsume(queueName, false, (consumerTag, delivery) -> {
    try {
        // Логика обработки сообщения
        processMessage(delivery.getBody());
        // Подтверждение успешной обработки
        channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
    } catch (Exception e) {
        // Ошибка обработки. Возвращаем сообщение в очередь для повторной попытки.
        channel.basicNack(delivery.getEnvelope().getDeliveryTag(), false, true);
    }
});

Почему это важно: Правильная обработка неудач гарантирует надежность — ни одно сообщение не будет потеряно из-за временного сбоя потребителя.