JBoss Messaging Performance Tuning Tips
1. Avoid persistent messages if possible
This is where the biggest gains are to be had. Always try and design your system to avoid using persistent messages. Persistent messages, by definition, need to be persisted, and persistence is expensive. In many cases systems can be designed to be tolerant to missing or duplicate messages, for instance a stock ticker application, where later messages override the data from earlier messages, and duplicates can be discarded by the application. If you can design your application in such a way it is well worth doing so.
2. Avoid XA
XA is very expensive. A single transaction involves several writes and syncs to the disk by both the transaction manager and the individual XAresources which include JBoss Messaging and any other XAResources - e.g. a database that may be enlisted in the same transaction. It is often possible to avoid XA altogether and get the same level of ACID transactions by employing a duplicate detection technique at the application level. You can associate each message with an application defined sequence number, and your application keeps track of the last sequence number it received (it will need to persist this). After failure occurs it will start to receive messages again. If it detects it has received a duplicate it simply discards it.
3. JGroups Performance Tuning Tips
The out of the box JGroups configuration (1.4.0.SP1 or later) runs with a TCP based stack for data traffic - for small clusters the TCP stack seems to give better performance. For larger clusters, you may get better performance using a UDP based stack. UDP tends to come into its own with large clusters. Remember that JGroups is highly tunable. Also see JGroups Performance Tuning Page for more information on tuning the network for optimal JGroups performance.
4. Avoid Message Pull between nodes
Avoid message pulling between nodes wherever necessary. Try and design your system where you have a homogeneous spread of producers and consumers across your nodes, so message pulling is not necessary. There will always be some performance hit when pulling messages from one node to another, especially for persistent messages, since they have to be removed from one node and inserted into the other.
If you do need message pulling, then ensure the attribute "UseXAForMessagePull" is set to false on the Server Peer. This means it will not use an XA transaction for removing the message from one node and inserting into the other.
5. Avoid too many consumers on queues with selectors
Having many consumers with different selectors on a queue will cause the entire queue to continually scanned for matching messages. Unfortunately the JMS specification allows this but it is very hard to implement with good performance. If possible, try and design your system otherwise. Having many consumers with selectors on a topic does not suffer from the same problem and should be used instead where possible.
6. Tune the consumer buffer size (the "prefetch" buffer)
By default each consumer maintains a client side buffer of messages. This is governed by the attribute "PrefetchSize" on the connection factory. You may want to increase this for very high throughput non persistent messages.
7. Avoid slow consumers
Make sure the attribute "SlowConsumers" is set to false on the connection factory, or client side buffering will turned off altogether.
8. Avoid anti-patterns
8.1 Avoid creating too many connections
Connection creation is a slow and heavyweight operation. Always try and re-use connections.
8.2 Avoid creating too many sessions/consumers
Although not as heavyweight as connections, session and consumers also require server side resources to be allocated so you should always try and re-use them too.
8.3 Always close your connections in a finally block
9. Avoid using the Spring JMSTemplate
There are multiple issues with this, see this page for more information.
10. Increase RAM and don't use paging
Avoid automatic queue paging if possible. This can introduce performance penalties due to the extra persistence it has to do. If possible try and fit all your queues / subscriptions in memory by increasing available RAM and setting the "fullSize" parameter on your queues / topics to a sufficiently large figure.
11. Avoid transacted or client acknowledge sessions when clustering
Transacted or client acknowledge sessions require session replication to maintain their semantics on failover, AUTO_ACKNOWLEDGE and DUPS_OK_ACKNOWLEDGE do not. If you can design your system to use AUTO_ACKNOWLEDGE or DUPS_OK_ACKNOWLEDGE sessions and maintain ACID semantics where necessary by duplicate detection, then you will not get the extra hit imposed by replication.
12. Tune the DUPS_OK batch size when using DUPS_OK acknowledge
A note about synching to disk.
When making performance comparisons, it's good to note that other messaging systems often ship with "synch to disk" off in their default, out of the box configuration. This can make their performance seem artifically high since they're not actually writing your message or transaction to disk when you think they are. If the system crashes there is a good chance you will lose data if you don't synch to disk. Make sure you turn "synch to disk" on to get an understanding of their real performance.