One of the easiest ways to tune an ActiveMQ deployment to increase scaleability is reduce the number of threads used to get the work done. The default ActiveMQ configuration makes use of several threads to isolate producers from consumers. This prevents a producer from blocking when a consumer is misbehaving. The following diagram shows the threads involved in the typical process of sending a message from a producer application to a consumer application.
ActiveMQ has several options that change the way threads are used and allocated. Understanding these options and knowing how they can impact the system will help you know if they are safe to enable on your system to reduce the number of threads used and thereby increase scaleability.
For example, the default configuration of the VM transport allocates a Transport Thread which polls for messages from the transport and delivers them to the connection. The VM transport considers this async delivery of messages. Since the VM transport connects to its transport peer within the same JVM, it’s possible to use the calling transport’s thread to deliver the message to connection instead of using the polling thread. When the aysnc=false option is used, the threads in the system look like the following diagram.
The broker uses a Dispatch Thread when sending messages to another connection. This isolates the producer’s Application Thread from any problems that may occur with the consumer’s connection. The dispatching of a message over Transport can be a blocking operation if there are problems with the network connection or if the client is misbehaving. The broker avoids blocking the producer’s thread even when the consumer’s connection is blocked by using this Dispatch Thread.
The broker supports an option to avoid using the Dispatch Thread and instead have the producer’s Transport Thread directly send the message over the consumer’s transport. This option should only be used when either you don’t mind blocking the producer when a consumer problem occurs or you know you won’t have consumer problems. This option can be enabled per consumer by settingdispatchAsync=false. The thread usage diagram for this option is shown below:
If you look at the consumer JVM, you see at least 2 threads when you create a consumer that uses a MessageListener. The first thread is the Transport Thread which polls and delivers messages from the underlying network. The second thread is the Session Thread which delivers the message to the MessageListener and processed the message. By using a Session Thread, ActiveMQ frees up the Transport Thread to continue to receive more messages from the network.
ActiveMQ has an option that can disable the creation and use of the Session Thread. When the optimizedDispatch=true option is enabled, the Transport Thread deliver the message directly to the MessageListener for processing. I would only recommend that this be used for simple MessageListeners that do not send messages back into the JMS system and which execute quickly. Please note that if you have multiple sessions, the consumers in each session will be serviced by a single Transport Thread, which makes the system less concurrent. The thread usage diagram for this option is shown below:
If you combine all the options listed above it is possible to achieve Straight Through Processing (STP), which can be a VERY performant way to process messages.