Red Hat Training

A Red Hat training course is available for Red Hat Fuse

Appendix A. Optimizing Performance of JMS Single- and Multiple-Resource Transactions

Abstract

There are many ways you can optimize the performance of JMS transactions—both single-source transactions that use the resource's internal transaction manager and multiple-resource transactions that use an external XA transaction manager.

Optimization tips for all JMS transactions

These tips apply to both single- and multiple-resource transactions:
  • When working with Spring JMS/camel-jms, use a pooling-enabled Connection Factory, such as ActiveMQ’s PooledConnectionFactory, to prevent clients from reopening JMS connections to the broker for each message consumed.
  • When using camel-jms to do local transactions through an external transaction manager, configure the transaction manager to use a pooling-enabled Connection Factory.
  • ActiveMQ’s PooledConnectionFactory eagerly fills the internal connection pool, the size of which is bound by the maxConnections property setting.
    Each call to PooledConnectionFactory.createConnection() creates and adds a new connection to the pool until maxConnections is reached, regardless of the number of connections in use. Once maxConnections is reached, the pool hands out only connections it recycles. So different JMS sessions (in different threads) can potentially share the same JMS connection, which the JMS specification specifically allows.
    Note
    The PooledConnectionFactory also pools JMS sessions, but the session pool behaves differently than the connection pool. The session pool creates new sessions only when there are no free sessions in it.
  • A camel-jms consumer configuration needs only one JMS connection from the connection pool, regardless of the setting of the concurrentConsumers property. As multiple camel routes can share the same PooledConnectionFactory, you can configure the pool’s maxConnections property equal to the number of Camel routes sharing it.
  • For local (transacted="true") JMS transaction using the activemq component, duplicate messages can occur on
 failover from master to slave. To prevent this from happening, set the
 lazyCreateTransactionManager property to
 false. NOTE: Do not set this property to false for XA transactions

Optimization tips for JMS XA transactions

These tips apply to multiple-resource transactions only:
  • With XA transactions, you must use CACHE_NONE or CACHE_CONNECTION in camel-jms or plain Spring JMS configurations. As CACHE_CONSUMER is not supported in these configurations, you need to use a pooling-enabled JMS Connection Factory to avoid opening a new connection for every message consumed.
  • Configure a prefetch of 1 on the ActiveMQ ConnectionFactory when not caching JMS consumers to eliminate any overhead generated by eager dispatch of messages to consumers. For example,
    failover:(tcp://localhost:61616)?jms.prefetchPolicy.all=1
  • When working with JMS providers other than ActiveMQ, wrap the 3rd-party JMS drivers in the generic XA-aware JcaPooledConnectionFactory (for details, see Section 6.6, “Generic XA-Aware Connection Pool Library”). For example, to wrap a WebSphereMQ endpoint:
    <bean id="FuseWmqXaConnectionFactory" class="org.apache.activemq.jms.pool.JcaPooledConnectionFactory">
      <property name="connectionFactory" ref="WMQConnectionFactory"/> 
      <property name="transactionManager" ref="transactionManager"/>
      <property name="maxConnections" value="5"/>
      <!-- note we set a unique name for the XA resource" -->
      <property name="name" value="ibm-wmq" />
    </bean>
    <bean id="WMQConnectionFactory" class="com.ibm.mq.jms.MQXAConnectionFactory">
      <property name="hostName" value="localhost" />
      <property name="port" value="1414" />
      <property name="queueManager" value="QM_VM" />
      <property name="channel" value="TEST" />
      <property name="transportType" value="1" />
    </bean>
    The wrapper provides the means for the Aries/Geronimo transaction manager to access and write the name of the participating WebSphereMQ resource to its HOWL recovery log file. This and other information stored in its recovery log file enables Aries to recover any pending transactions after a crash occurs.
  • Always declare a resource manager for each resource involved in an XA transaction. Without a resource manager, pending XA transactions cannot be recovered after a JBoss Fuse crash, resulting in lost messages.