Chapter 7. Messaging subsystem tuning When statistics collection is enabled for a messaging server in the messaging-activemq subsystem, you can view runtime statistics for resources on the messaging server. 7.1. Enabling messaging statistics Because it can negatively impact performance, statistics collection for the messaging-activemq subsystem is not enabled by default. You do not need to enable queue statistics to obtain basic information, such as the number of messages on a queue or the number of messages added to a queue. Those statistics are available using queue attributes without requiring that you set statistics-enabled to true . You can enable additional statistics collection using the management CLI or the management console. 7.1.1. Enable messaging statistics using the management CLI The following management CLI command enables the collection of statistics for the default messaging server. Pooled connection factory statistics are enabled separately from the other messaging server statistics. Use the following command to enable statistics for a pooled connection factory. Reload the server for the changes to take effect. 7.1.2. Enable messaging statistics using the management console Use the following steps to enable statistics collection for a messaging server using the management console. Procedure Navigate to Configuration Subsystems Messaging (ActiveMQ) Server . Select the server and click View . Click Edit under the Statistics tab. Set the Statistics Enabled field to ON and click Save . Pooled connection factory statistics are enabled separately from the other messaging server statistics. Use the following steps to enable statistics collection for a pooled connection factory. Navigate to Configuration Subsystems Messaging (ActiveMQ) Server . Select the server, select Connections , and click View . Select the Pooled Connection Factory tab. Select the pooled connection factory and click Edit under the Attributes tab. Set the Statistics Enabled field to ON and click Save . Reload the server for the changes to take effect. 7.2. Viewing messaging statistics You can view runtime statistics for a messaging server using the management CLI or management console. 7.2.1. View messaging statistics using the management CLI You can view messaging statistics using the following management CLI commands. Be sure to include the include-runtime=true argument as statistics are runtime information. View statistics for a queue. View statistics for a topic. View statistics for a pooled connection factory. Note Pooled connection factory statistics are enabled separately from the other messaging server statistics. 7.2.2. View messaging statistics using the management console To view messaging statistics from the management console, navigate to the Messaging (ActiveMQ) subsystem from the Runtime tab, and select the server. Select a destination to view its statistics. Note The Prepared Transactions page is where you can view, commit, and roll back prepared transactions. 7.3. Configure message counters You can configure the following message counter attributes for a messaging server. message-counter-max-day-history : The number of days the message counter history is kept. message-counter-sample-period : How often, in milliseconds, the queue is sampled. The management CLI command to configure these options uses the following syntax. Be sure to replace `STATISTICS_NAME` and `STATISTICS_VALUE` with the statistic name and value you want to configure. For example, use the following commands to set the message-counter-max-day-history to five days and the message-counter-sample-period to two seconds. 7.4. View message counter and history for a queue You can view the message counter and message counter history for a queue using the following management CLI operations. list-message-counter-as-json list-message-counter-as-html list-message-counter-history-as-json list-message-counter-history-as-html The management CLI command to use display these values uses the following syntax. Be sure to replace `QUEUE_NAME` and `OPERATION_NAME` with the queue name and operation you want to use. For example, use the following command to view the message counter for the TestQueue queue in JSON format. 7.5. Reset message counter for a queue You can reset the message counter for a queue using the reset-message-counter management CLI operation. 7.6. Runtime operations using the management console Using the management console you can: Perform forced failover to another messaging server Reset all message counters for a messaging server Reset all message counters history for a messaging server View information related to a messaging server Close connections for a messaging server Roll back transactions Commit transactions 7.6.1. Perform forced failover to another messaging server You can use the management console to perform a forced failover to another messaging server. Procedure Access the management console and navigate to Server using either of the following: Runtime -> Browse By Hosts Host Server Runtime -> Browse By Server Groups Server Group Server Click Messaging ActiveMQ Server Click the arrow button to View and click Force Failover . On the Force Failover window, click Yes . 7.6.2. Resetting all message counters for a messaging server You can use the management console to reset all message counters for a messaging server. Procedure Access the management console and navigate to Server using either of the following: Runtime -> Browse By Hosts Host Server Runtime -> Browse By Server Groups Server Group Server Click Messaging ActiveMQ Server Click the arrow button to View and click Reset . On the Reset window, click the toggle button to Reset all message counters to enable the functionality. The button now displays ON in a blue background. Click Reset . 7.6.3. Resetting message counters history for a messaging server You can use the management console to reset message counters history for a messaging server. Procedure Access the management console and navigate to Server using either of the following: Runtime -> Browse By Hosts Host Server Runtime -> Browse By Server Groups Server Group Server Click Messaging ActiveMQ Server Click the arrow button to View and click Reset . On the Reset window, click the toggle button to Reset all message counters history to enable the functionality. The button now displays ON in a blue background. Click Reset . 7.6.4. View information related to a messaging server Using the management console you can view a list of the following information related to a messaging server: Connections Consumers Producers Connectors Roles Transactions To view information related to a messaging server: Procedure Access the management console and navigate to Server using either of the following: Runtime -> Browse By Hosts Host Server Runtime -> Browse By Server Groups Server Group Server Click Messaging ActiveMQ Server and then click View . Click the appropriate item on the navigation pane to view a list of the item on the right pane. 7.6.5. Close connections for a messaging server You can close connections by providing an IP address, an ActiveMQ address match or a user name. To close connections for a messaging server: Procedure Access the management console and navigate to Server using either of the following: Runtime -> Browse By Hosts Host Server Runtime -> Browse By Server Groups Server Group Server Click Messaging ActiveMQ Server and then click View . On the navigation pane, click Connections . On the Close window, click the appropriate tab based on which connection you want to close. Based on your selection, enter the IP address, ActiveMQ address match, or the user name, and then click Close . 7.6.6. Rolling back transactions for a messaging server You can use the management console to roll back transactions for a messaging server. Procedure Access the management console and navigate to Server using either of the following: Runtime -> Browse By Hosts Host Server Runtime -> Browse By Server Groups Server Group Server Click Messaging ActiveMQ Server and then click View . On the navigation pane, click Transactions . Select the transaction you want to roll back and click Rollback . 7.6.7. Committing transactions for a messaging server You can use the management console to commit transactions for a messaging server. Procedure Access the management console and navigate to Server using either of the following: Runtime -> Browse By Hosts Host Server Runtime -> Browse By Server Groups Server Group Server Click Messaging ActiveMQ Server and then click View . On the navigation pane, click Transactions . Select the transaction you want to commit and click Commit . 7.7. Tuning Jakarta Messaging If you use the Jakarta Messaging API, review the following information for tips on how to improve performance. Disable the message ID. If you do not need message IDs, disable them by using the setDisableMessageID() method on the MessageProducer class. Setting the value to true eliminates the overhead of creating a unique ID and decreases the size of the message. Disable the message timestamp. If you do not need message timestamps, disable them by using the setDisableMessageTimeStamp() method on the MessageProducer class. Setting the value to true eliminates the overhead of creating the timestamp and decreases the size of the message. Avoid using ObjectMessage . ObjectMessage is used to send a message that contains a serialized object, meaning the body of the message, or payload, is sent over the wire as a stream of bytes. The Java serialized form of even small objects is quite large and takes up a lot of space on the wire. It is also slow when compared to custom marshalling techniques. Use ObjectMessage only if you cannot use one of the other message types, for example, if you do not know the type of the payload until runtime. Avoid AUTO_ACKNOWLEDGE . The choice of acknowledgement mode in a consumer impacts performance because of the additional overhead and traffic incurred by sending the acknowledgment message sent over the network. AUTO_ACKNOWLEDGE incurs this overhead because it requires an acknowledgement to be sent from the server for each message received on the client. If you can, use DUPS_OK_ACKNOWLEDGE , which acknowledges messages in a lazy manner, CLIENT_ACKNOWLEDGE , meaning the client code will call a method to acknowledge the message, or batch up many acknowledgements with one acknowledge or commit in a transacted session. Avoid durable messages. By default, Jakarta Messaging messages are durable. If you do not need durable messages, set them to be non-durable . Durable messages incur a lot of overhead because they are persisted to storage. Use TRANSACTED_SESSION mode to send and receive messages in a single transaction. By batching messages in a single transaction, the ActiveMQ Artemis server integrated in JBoss EAP requires only one network round trip on the commit, not on every send or receive. 7.8. Tuning persistence Put the message journal on its own physical volume. One of the advantages of an append-only journal is that disk head movement is minimized. This advantage is lost if the disk is shared. When multiple processes, such as a transaction coordinator, databases, and other journals, read and write from the same disk, performance is impacted because the disk head must skip around between different files. If you are using paging or large messages, make sure they are also put on separate volumes. Tune the journal-min-files value. Set the journal-min-files parameter to the number of files that fits your average sustainable rate. If you frequently see new files being created on the journal data directory, meaning a lot data is being persisted, you need to increase the minimal number of files. This allows the journal to reuse, rather than create, new data files. Optimize the journal file size. The journal file size must be aligned to the capacity of a cylinder on the disk. The default value of 10MB should be enough on most systems. Use the AIO journal type. For Linux operating systems, keep your journal type as AIO . AIO scales better than Java NIO . Tune the journal-buffer-timeout value. Increasing the journal-buffer-timeout value results in increased throughput at the expense of latency. Tune the journal-max-io value. If you are using AIO , you might be able improve performance by increasing the journal-max-io parameter value. Do not change this value if you are using NIO . 7.9. Other tuning options This section describes other places in JBoss EAP messaging that can be tuned. Use asynchronous send acknowledgements. If you need to send non-transactional, durable messages and do not need a guarantee that they have reached the server by the time the call to send() returns, do not set them to be sent blocking. Instead use asynchronous send acknowledgements to get your send acknowledgements returned in a separate stream. However, in the case of a server crash, some messages might be lost. Use pre-acknowledge mode. With pre-acknowledge mode, messages are acknowledged before they are sent to the client. This reduces the amount of acknowledgment traffic on the wire. However, if that client crashes, messages will not be redelivered if the client reconnects. Disable security. There is a small performance boost when you disable security by setting the security-enabled attribute to false. Disable persistence. You can turn off message persistence altogether by setting persistence-enabled to false . Sync transactions lazily. Setting journal-sync-transactional to false provides better transactional persistent performance at the expense of some possibility of loss of transactions on failure. Sync non-transactional lazily. Setting journal-sync-non-transactional to false provides better non-transactional persistent performance at the expense of some possibility of loss of durable messages on failure. Send messages non-blocking. To avoid waiting for a network round trip for every message sent, set block-on-durable-send and block-on-non-durable-send to false if you are using Jakarta Messaging and JNDI, or set it directly on the ServerLocator by calling the setBlockOnDurableSend() and setBlockOnNonDurableSend() methods. Optimize the consumer-window-size . If you have very fast consumers, you can increase the consumer-window-size to effectively disable consumer flow control. Use the core API instead of the Jakarta Messaging API. Jakarta Messaging operations must be translated into core operations before the server can handle them, resulting in lower performance than when you use the core API. When using the core API, try to use methods that take SimpleString as much as possible. SimpleString , unlike java.lang.String , does not require copying before it is written to the wire, so if you reuse SimpleString instances between calls, you can avoid some unnecessary copying. Note that the core API is not portable to other brokers. 7.10. Avoiding anti-patterns Reuse connections, sessions, consumers, and producers where possible. The most common messaging anti-pattern is the creation of a new connection, session, and producer for every message sent or consumed. These objects take time to create and may involve several network round trips, so it is a poor use of resources. Always reuse them. Note Some popular libraries such as the Spring Messaging Template use these anti-patterns. If you are using the Spring Messaging Template, you may see poor performance. The Spring Messaging Template can only safely be used in an application server which caches Jakarta Messaging sessions, for example, using Jakarta Connectors, and only then for sending messages. It cannot safely be used for synchronously consuming messages, even in an application server. Avoid fat messages. Verbose formats such as XML take up a lot of space on the wire and performance suffers as result. Avoid XML in message bodies if you can. Do not create temporary queues for each request. This common anti-pattern involves the temporary queue request-response pattern. With the temporary queue request-response pattern, a message is sent to a target, and a reply-to header is set with the address of a local temporary queue. When the recipient receives the message, they process it, and then send back a response to the address specified in the reply-to header. A common mistake made with this pattern is to create a new temporary queue on each message sent, which drastically reduces performance. Instead, the temporary queue should be reused for many requests. Do not use message driven beans unless it is necessary. Using MDBs to consume messages is slower than consuming messages using a simple Jakarta Messaging message consumer.

Commands:
/subsystem=messaging-activemq/server=default:write-attribute(name=statistics-enabled,value=true)
/subsystem=messaging-activemq/server=default/pooled-connection-factory=activemq-ra:write-attribute(name=statistics-enabled,value=true)
/subsystem=messaging-activemq/server=default/jms-queue=DLQ:read-resource(include-runtime=true) { "outcome" => "success", "result" => { "consumer-count" => 0, "dead-letter-address" => "jms.queue.DLQ", "delivering-count" => 0, "durable" => true, } }
/subsystem=messaging-activemq/server=default/jms-topic=testTopic:read-resource(include-runtime=true) { "outcome" => "success", "result" => { "delivering-count" => 0, "durable-message-count" => 0, "durable-subscription-count" => 0, } }
/subsystem=messaging-activemq/server=default/pooled-connection-factory=activemq-ra/statistics=pool:read-resource(include-runtime=true) { "outcome" => "success", "result" => { "ActiveCount" => 1, "AvailableCount" => 20, "AverageBlockingTime" => 0L, "AverageCreationTime" => 13L, "AverageGetTime" => 14L, } }
/subsystem=messaging-activemq/server=default::write-attribute(name=STATISTICS_NAME,value=STATISTICS_VALUE)
/subsystem=messaging-activemq/server=default:write-attribute(name=message-counter-max-day-history,value=5) /subsystem=messaging-activemq/server=default:write-attribute(name=message-counter-sample-period,value=2000)
/subsystem=messaging-activemq/server=default/jms-queue=QUEUE_NAME:OPERATION_NAME
/subsystem=messaging-activemq/server=default/jms-queue=TestQueue:list-message-counter-as-json { "outcome" => "success", "result" => "{\"destinationName\":\"TestQueue\",\"destinationSubscription\":null,\"destinationDurable\":true,\"count\":0,\"countDelta\":0,\"messageCount\":0,\"messageCountDelta\":0,\"lastAddTimestamp\":\"12/31/69 7:00:00 PM\",\"updateTimestamp\":\"2/20/18 2:24:05 PM\"}" }
/subsystem=messaging-activemq/server=default/jms-queue=TestQueue:reset-message-counter { "outcome" => "success", "result" => undefined }