Using Apache ActiveMQ
I use Apache ActiveMQ for internal component communicatino in a project of mine. As only local (no distributed or network) communication is needed I configured it to use the VM transport, the fasted and most efficient way according to the online documentation. To prevent overhead objects instead of serialized XML is send through the queue – profiling has shown that using JDOM‘s XmlOutputter to generate XML is a major cpu hog. Another advantage of using the VM transport is that no dedicated broker is needed, the internal one is started automatically. So everything is peachy?
Unfortunately not.
The first profile run (using Profiler4J) showed unusual high cpu load while the system was running idle. Further analysis showed that ActiveMQ’s message receive function does do polling to get messages from the queue. This only affects the framework when running idle and shouldn’t use as much cpu when there’s actual work to do but still this is highly disturbing. After investigating the ActiveMQ documentation again (on a side node: there seems to be something that automatically destroys anything resembling documentation as soon as a project joins Apache) I found out that there’s another way of receiving messages. As it was an asynchronous listener based approach it should be easier on the processor. As a nice side effect the receiver side of my application’s action got simpler too.
Better results? No.
More than half of the systems CPU usage in the “now-not-idle-mode-anymore” still is generated by polled message queues. My solution to that problem (due to lack of documentation) was ripping out the ActiveMQ part altogether and replacing it with a simple java.util.concurrent.BlockingQueue. It is thread-safe, simple to use and does a sort of sender side blocking (through a predefined queue size). In addition the data structure is a generic one, so some type-casts are avoided. CPU usage went down, a lot!
So what am I missing in the ActiveMQ picture? As it claims enterprise-grade this should not happen so I’m expecting an error on my side.
No related posts.
Any chance you could post your code to the user forums – from your blog post its impossible to diagnose whats going on.
http://activemq.apache.org/discussion-forums.html
It could be a mistake in your Java code etc? Also make sure you’re always using the latest greatest release of ActiveMQ
This isn’t that easy anymore (as the code in question was ripped out), but I have another project that uses the same activeMQ configuration, albeit configured through Spring. The profile run was comparable to the original problem.
This are the major ActiveMQ related parts:
<!– message queue initialization –>
<bean id=”connectionFactory”
class=”org.apache.activemq.ActiveMQConnectionFactory”>
<property name=”brokerURL”
value=”vm://localhost?broker.persistent=false” />
</bean>
<!– a javax.jms.Connection –>
<bean id=”connection” factory-bean=”connectionFactory”
factory-method=”createConnection” init-method=”start” />
<!– a jms session –>
<bean id=”session” factory-bean=”connection”
factory-method=”createSession”>
<constructor-arg value=”false” />
<constructor-arg>
<bean id=”javax.jms.Session.AUTO_ACKNOWLEDGE”
class=”org.springframework.beans.factory.config.FieldRetrievingFactoryBean” />
</constructor-arg>
</bean>
<!– the destination (Topic or Queue) –>
<bean id=”mailDestination” factory-bean=”session”
factory-method=”createQueue”>
<constructor-arg value=”mailqueue” />
</bean>
<!– anonymous consumer – message queue <-> persistence manager wiring –>
<bean factory-bean=”session” factory-method=”createConsumer”>
<constructor-arg ref=”mailDestination” />
<property name=”messageListener”
ref=”passthroughPersistenceManager” />
</bean>