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.
/subsystem=messaging-activemq/server=default:write-attribute(name=statistics-enabled,value=true)
/subsystem=messaging-activemq/server=default:write-attribute(name=statistics-enabled,value=true)
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.
/subsystem=messaging-activemq/server=default/pooled-connection-factory=activemq-ra:write-attribute(name=statistics-enabled,value=true)
/subsystem=messaging-activemq/server=default/pooled-connection-factory=activemq-ra:write-attribute(name=statistics-enabled,value=true)
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.
/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-queue=DLQ:read-resource(include-runtime=true)
{
"outcome" => "success",
"result" => {
"consumer-count" => 0,
"dead-letter-address" => "jms.queue.DLQ",
"delivering-count" => 0,
"durable" => true,
...
}
}
- View statistics for a topic.
/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/jms-topic=testTopic:read-resource(include-runtime=true)
{
"outcome" => "success",
"result" => {
"delivering-count" => 0,
"durable-message-count" => 0,
"durable-subscription-count" => 0,
...
}
}
- View statistics for a pooled connection factory.
/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/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,
...
}
}
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.
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.
/subsystem=messaging-activemq/server=default::write-attribute(name=STATISTICS_NAME,value=STATISTICS_VALUE)
/subsystem=messaging-activemq/server=default::write-attribute(name=STATISTICS_NAME,value=STATISTICS_VALUE)
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.
/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:write-attribute(name=message-counter-max-day-history,value=5)
/subsystem=messaging-activemq/server=default:write-attribute(name=message-counter-sample-period,value=2000)
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.
/subsystem=messaging-activemq/server=default/jms-queue=QUEUE_NAME:OPERATION_NAME
/subsystem=messaging-activemq/server=default/jms-queue=QUEUE_NAME:OPERATION_NAME
For example, use the following command to view the message counter for the TestQueue
queue in JSON format.
/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: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\"}"
}
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.
/subsystem=messaging-activemq/server=default/jms-queue=TestQueue:reset-message-counter { "outcome" => "success", "result" => undefined }
/subsystem=messaging-activemq/server=default/jms-queue=TestQueue:reset-message-counter
{
"outcome" => "success",
"result" => undefined
}
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
-
Runtime→ Browse By
-
Click Messaging ActiveMQ
Server - Click the arrow button next 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
-
Runtime→ Browse By
-
Click Messaging ActiveMQ
Server - Click the arrow button next to View and click Reset.
On the Reset window, click the toggle button next 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
-
Runtime→ Browse By
-
Click Messaging ActiveMQ
Server - Click the arrow button next to View and click Reset.
On the Reset window, click the toggle button next to Reset all message counters history to enable the functionality.
The button now displays
ON
in a blue background.- Click Reset.
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
-
Runtime→ Browse By
-
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
-
Runtime→ Browse By
-
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
-
Runtime→ Browse By
-
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 theMessageProducer
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 theMessageProducer
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. UseObjectMessage
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, useDUPS_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 JavaNIO
.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 thejournal-max-io
parameter value. Do not change this value if you are usingNIO
.
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
tofalse
.Sync transactions lazily.
Setting
journal-sync-transactional
tofalse
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
tofalse
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
andblock-on-non-durable-send
tofalse
if you are using Jakarta Messaging and JNDI, or set it directly on theServerLocator
by calling thesetBlockOnDurableSend()
andsetBlockOnNonDurableSend()
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
, unlikejava.lang.String
, does not require copying before it is written to the wire, so if you reuseSimpleString
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.
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.