Chapter 3. Consumer Performance

3.1. Acknowledgment Modes

Overview

The choice of acknowledgement mode in a consumer has a large impact on performance, because each acknowledgment message incurs the overhead of a message send over the network. The key to improving performance in this area is to send acknowledgments in batches, rather than acknowledging each message individually.

Supported acknowledgment modes

Red Hat JBoss A-MQ supports the following acknowledgment modes:
Session.AUTO_ACKNOWLEDGE
(Default) In this mode, the JMS session automatically acknowledges messages as soon as they are received. In particular, the JMS session acknowledges messages before dispatching them to the application layer. For example, if the consumer application calls MessageConsumer.receive(), the message has already been acknowledged before the call returns.
Session.CLIENT_ACKNOWLEDGE
In this mode, the client application code explicitly calls the Message.acknowledge() method to acknowledge the message. In Apache Camel, this acknowledges not just the message on which it is invoked, but also any other messages in the consumer that have already been completely processed.
Session.DUPS_OK_ACKNOWLEDGE
In this mode, the JMS session automatically acknowledges messages, but does so in a lazy manner. If JMS fails while this mode is used, some messages that were completely processed could remain unacknowledged. When JMS is restarted, these messages will be re-sent (duplicate messages).
This is one of the fastest acknowledgment modes, but the consumer must be able to cope with possible duplicate messages (for example, by detecting and discarding duplicates).
Session.SESSION_TRANSACTED
When using transactions, the session implicitly works in SESSION_TRANSACTED mode. The response to the transaction commit is then equivalent to message acknowledgment.
When JMS transactions are used to group multiple messages, transaction mode is very efficient. But avoid using a transaction to send a single message, because this incurs the extra overhead of committing or rolling back the transaction.
ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE
This non-standard mode is similar to CLIENT_ACKNOWLEDGE, except that it acknowledges only the message on which it is invoked. It does not flush acknowledgments for any other completed messages.

optimizeAcknowledge option

The optimizeAcknowledge option is exposed on the ActiveMQConnectionFactory class and must be used in conjunction with the Session.AUTO_ACKNOWLEDGE mode. When set to true, the consumer acknowledges receipt of messages in batches, where the batch size is set to 65% of the prefetch limit. Alternatively, if message consumption is slow, the batch acknowledgment will be sent after 300ms. Default is false.
You can set this option on a consumer URI, as follows:
tcp://hostA:61617?jms.optimizeAcknowledge=true
Note
The optimizeAcknowledge option is only supported by the JMS client API.

Choosing the acknowledgment mode

In general, you can achieve the best performance either using JMS transactions, and grouping several messages into a single transaction, or by selecting the DUPS_OK_ACKNOWLEDGE mode, which requires you to implement duplicate detection code in your consumer.
A typical strategy for implementing duplicate detection is to insert a unique message ID in a JMS header on the producer side and then to store the received IDs on the consumer side. If you are using Red Hat JBoss A-MQ in combination with Apache Camel, you can easily use the Idempotent Consumer pattern to implement duplicate detection.