Updated on 2022-09-13 GMT+08:00

Message Acknowledgment

Scenario

How does a producer confirm that a message has been properly published to the server? How does the server confirm that a message has been successfully consumed? The answer is RabbitMQ's acknowledgement mechanism.

Acknowledgments by publishers ("publisher confirms") and consumers are critical to ensure data reliability. If a connection fails, messages being transmitted may be lost and need to be transmitted again. The acknowledgment mechanism enables the server and client to know when to retransmit messages. A client may acknowledge a message upon receipt of the message, or after it has completely processed the message. Producer confirms affect performance and should be disabled if high throughput is required. However, disabling producer confirms leads to lower reliability.

For details about the message acknowledgment mechanism, see Consumer Acknowledgment and Publisher Confirms.

Producer Confirms

The server confirms that it has received the message sent from the producer.

The following example shows how to configure publisher confirms on a Java client.

try {
	channel.confirmSelect(); // Enable publisher confirms on the channel.
	// Send messages normally.
	channel . basicPublish( "exchange " , " routingKey" , null , "publisher confirm test " .getBytes());
	if (!channel.waitForConfirms()) {
		System.out.println( "send message failed " ) ;
		// do something else....
	}
} catch (InterruptedException e) {
		e.printStackTrace() ;
}

After the channel .waitForConfirms method is called, the system waits for a confirmation from the server. Such synchronous waiting affects performance, but is necessary if the publisher requires at-least-once delivery.

Consumer Acknowledgment

The server determines whether to delete a message from a queue based on whether the message is successfully received by the consumer.

Consumer acknowledgments are important to ensure data reliability. Consumer applications should take enough time to process important messages before acknowledging the messages. In this way, we do not have to worry about message losses caused by consumer process exceptions (such as program breakdown and restart) during message processing.

Consumer acknowledgment can be enabled by using the basicConsume method. In most cases, consumer acknowledgments are enabled on channels.

The following example shows how to configure consumer acknowledgments on a Java client (using Channel#basicAck and basic.ack for positive acknowledgment):

// this example assumes an existing channel instance

boolean autoAck = false;
channel.basicConsume(queueName, autoAck, "a-consumer-tag",
     new DefaultConsumer(channel) {
         @Override
         public void handleDelivery(String consumerTag,
                                    Envelope envelope,
                                    AMQP.BasicProperties properties, byte[] body)
             throws IOException
         {
             long deliveryTag = envelope.getDeliveryTag();
             // positively acknowledge a single delivery, the message will
             // be discarded
             channel.basicAck(deliveryTag, false);
         }
     });

Unacknowledged messages are cached in the memory. If there are too many unacknowledged messages, the memory usage becomes high. In this case, you can limit the number of messages prefetched by the consumer. For details, see Prefetch.