Exploring Manual and Automatic Acknowledgment in RabbitMQ with .NET
Delivery processing acknowledgements from consumers are referred to as acknowledgements in messaging protocols. Let's learn automatic and manual ack modes in RabbitMQ.
Table of Contents
Messages picked up for processing by the consumers are not guaranteed to be successfully processed.
Hence, consumers need a mechanism for processing confirmation.
Delivery processing acknowledgements from consumers are referred to as acknowledgements in messaging protocols.
In this post, let’s learn about different acknowledgement modes and how to use them when working with RabbitMQ from a .NET application.
The concept still applies to other programming languages.
There are two acknowledgement modes supported in RabbitMQ
- Automatic ACK
- Manual ACK
This article is sponsored by AWS and is part of my RabbitMQ Series.
Automatic Acknowledgement From .NET Application
The message is considered to be successfully delivered immediately after it's sent.
With Automatic ACK mode, there is a higher throughput of messages getting processed at the risk of losing some messages.
It can also cause the consumer to overload if many messages are in the queue.
channel.BasicConsume("hello", autoAck: true, consumer);
When registering the consumer with the RabbitMQ channel, you can specify autoAck
property true
to enable automatic acknowledgement, as shown above.
However, when using Automatic acknowledgement, when there are exceptions in message consumers these messages are completely lost from the Queue.
The code below throws an exception if the message received contains the word 'exception.' This message is processed and removed from the queue, even though the consumer threw an exception while processing.
consumer.Received += (model, ea) =>
{
var body = ea.Body.ToArray();
var message = Encoding.UTF8.GetString(body);
Console.WriteLine($"[x] Received message {message}");
if (message.Contains("exception"))
{
Console.WriteLine("Error in processing");
throw new Exception("Error in processing");
}
// Additional processing for this message
Console.WriteLine($"Processed message {message}");
};
Manual Acknowledgement From .NET Application
With Manual Acknowledgement, the consumer explicitly marks a message as processed successfully or failed.
RabbitMQ provides different protocol methods to acknowledge the messages:
- basic.ack
→ positive acknowledgements
- basic.nack
→ negative acknowledgement (also supports multiple messages)
- basic.reject
→ negative acknowledgement (single message only)
To use manual acknowledgement, specify autoAck
as false when registering a consumer to RabbitMQ using the channel.
channel.BasicConsume("hello", autoAck: false, consumer);
Delivery Tags
Delivery Tags are used to acknowledge deliveries. Every message delivered on a channel has an associated delivery tag.
Delivery tags are scoped to a channel, so the same channel must acknowledge a message using the received tag. Acknowledging messages with a delivery tag from a different channel will cause an exception and close that channel.
Below is the sample code in the RabbitMQ consumer to acknowledge (BasicAck
) and reject (BasicReject
) a message based on the consumer logic.
consumer.Received += (model, ea) =>
{
var body = ea.Body.ToArray();
var message = Encoding.UTF8.GetString(body);
Console.WriteLine($"[x] Received message {message}");
if (message.Contains("exception"))
{
Console.WriteLine("Error in processing");
channel.BasicReject(ea.DeliveryTag, false);
throw new Exception("Error in processing");
}
// Additional processing for this message
Console.WriteLine($"Processed message {message}");
channel.BasicAck(deliveryTag: ea.DeliveryTag, false);
};
Delivery Acknowledgement Timeout
If the consumer does not reply with a message within the Delivery Acknowledgement Timeout period, the channel will be closed with an PRECONDITION_FAILED
exception. All outstanding deliveries on that channel will be re-queued.
You can configure the consumer_timeout
value for your RabbitMQ instance.
In RabbitMQ hosted on Amazon MQ, you can do that under Amazon MQ → Configurations as shown below and assign that configuration to your RabbitMQ instance.
How you configure it will differ based on how you host your RabbitMQ instance.
Rabbit NACK vs Reject
The only difference between nack
and reject
is that, nack
supports rejecting multiple deliveries with a single call. It was for this reason nack
was introduced as a protocol extension.
Automatic acknowledgment is generally considered unsafe and unsuitable for all workloads. Choose only for scenarios where you don't need a guarantee on the message being processed.
For all other scenarios, manually acknowledge your messages!
Rahul Nath Newsletter
Join the newsletter to receive the latest updates in your inbox.