Ответ
Подтверждение (Acknowledge, ACK) — это механизм, с помощью которого потребитель (consumer) явно сообщает брокеру RabbitMQ, что сообщение было успешно получено и обработано. Это основа гарантированной доставки (at-least-once delivery).
Проблема, которую решает ACK: Без подтверждения (autoAck: true) сообщение немедленно удаляется из очереди после отправки потребителю. Если процесс потребителя упадёт во время обработки, сообщение будет потеряно навсегда.
Как работает ручное подтверждение (autoAck: false):
- RabbitMQ отправляет сообщение потребителю и помечает его как "неподтверждённое" (unacknowledged).
- Сообщение остаётся в очереди (логически, хотя и не доступно для других потребителей), пока не получит ACK.
- После успешной обработки потребитель отправляет
BasicAckсdeliveryTag(уникальный идентификатор доставки). - RabbitMQ удаляет сообщение из очереди.
Пример кода на .NET (RabbitMQ.Client):
var channel = connection.CreateModel();
channel.QueueDeclare("task_queue", durable: true, exclusive: false, autoDelete: false, arguments: null);
channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false); // Честное распределение
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (sender, ea) =>
{
var body = ea.Body.ToArray();
var message = Encoding.UTF8.GetString(body);
Console.WriteLine($" [x] Получено: {message}");
try
{
// Имитация обработки задачи
ProcessMessage(message);
// ЯВНОЕ ПОДТВЕРЖДЕНИЕ УСПЕШНОЙ ОБРАБОТКИ
channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
Console.WriteLine($" [v] Обработано и подтверждено: {message}");
}
catch (Exception ex)
{
Console.WriteLine($" [!] Ошибка обработки: {ex.Message}");
// Отрицательное подтверждение (NACK) с requeue = true
channel.BasicNack(deliveryTag: ea.DeliveryTag, multiple: false, requeue: true);
// Сообщение вернётся в очередь для повторной попытки обработки.
}
};
// Запуск потребителя с ВЫКЛЮЧЁННЫМ autoAck
channel.BasicConsume(queue: "task_queue", autoAck: false, consumer: consumer);
Типы подтверждений:
BasicAck: Положительное подтверждение. Сообщение можно удалять.BasicNack(Negative Acknowledgement): Отрицательное подтверждение. Сообщение можно либо отбросить, либо вернуть в очередь (requeue: true).BasicReject: Устаревший аналогBasicNackс одним флагомrequeue.
Итог: Использование ручного ACK критически важно для построения отказоустойчивых систем, где потеря сообщений недопустима.