简体   繁体   中英

Efficient use of consumers with Spring Integration and WebSphere when using XA transactions

I am using Spring Integration (2.2.0) with WebSphere (8.0.0.x), in order to send messages via JMS (Tibco EMS).

Communication between components is working fine, but we have observed huge latencies between the messaging hops. These are in line with what we see in the EMS logs:

2014-09-30 06:04:19.940 [user@host]: Destroyed consumer (connid=19202559, sessid=28728543, consid=328585032) on queue 'test.queue3.request'
2014-09-30 06:04:19.969 [user@host]: Created consumer (connid=19202564, sessid=28728551, consid=328585054) on queue 'test.queue2.request'
2014-09-30 06:04:20.668 [user@host]: Destroyed consumer (connid=19202562, sessid=28728549, consid=328585048) on queue 'test.queue1.request'
2014-09-30 06:04:20.733 [user@host]: Created consumer (connid=19202567, sessid=28728555, consid=328585071) on queue 'test.queue5.request'
2014-09-30 06:04:20.850 [user@host]: Destroyed consumer (connid=19202563, sessid=28728550, consid=328585051) on queue 'test.queue4.request'
2014-09-30 06:04:21.001 [user@host]: Destroyed consumer (connid=19202564, sessid=28728551, consid=328585054) on queue 'test.queue2.request'
2014-09-30 06:04:21.701 [user@host]: Created consumer (connid=19202571, sessid=28728561, consid=328585093) on queue 'test.queue3.request'
2014-09-30 06:04:21.762 [user@host]: Destroyed consumer (connid=19202567, sessid=28728555, consid=328585071) on queue 'test.queue5.request'

Apparently, consumers are constantly being destroyed and re-created. This is not only bad for EMS, but also it's killing the latency, as messages are not delivered until the consumer is back online.

This is how the consumers are defined:

<jee:jndi-lookup id="rawConnectionFactory" jndi-name="jms/QueueCF"/>

<bean id="jmsDestinationResolver"
      class="org.springframework.jms.support.destination.JndiDestinationResolver"/>

<bean id="connectionFactory"
      class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter"
      p:targetConnectionFactory-ref="rawConnectionFactory"
      p:username="${jms.internal.username}"
      p:password="${jms.internal.password}"/>

<bean id="taskExecutor"
      class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor"
      p:workManagerName="wm/mc"
      p:resourceRef="false"/>

<bean id="transactionManager"
      class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>

<bean id="adp1Container"
    class="org.springframework.jms.listener.DefaultMessageListenerContainer"
    p:taskExecutor-ref="taskExecutor"
    p:destinationName="requestQueue1" p:connectionFactory-ref="connectionFactory"
    p:destinationResolver-ref="jmsDestinationResolver"
    p:transactionManager-ref="transactionManager" />

<jms:inbound-gateway id="jmsInAdapter1"
    request-channel="adapter1logic" container="adp1Container" />

<channel id="adapter1logic" />

Update:

This behaviour is related to the use of the transaction manager.

If we specify the connection to the EMS server directly in Spring (indicating there the host, port, user, password), consumers are still constantly recreated, but for some reason these recreations are not affecting the end-to-end latencies. Connections are apparently being managed better in Spring than in WAS.

  • How to configure WAS so that consumers trigger as quick as in Spring?

If, along with the previous change, I also remove the reference to the transaction manager in the DefaultMessageListenerContainer, consumers stop destroying and constructing altogether.

  • What could be the issue with WebSphere's transaction manager? Why are consumers destroying and constructing when WAS' transaction manager is in use? Is there any configuration that can be adjusted?

You should not see consumers being recycled like that, unless your listener is throwing an exception. Container consumers a long-lived by default. I suggest you turn on DEBUG (or even TRACE) logging for the container to figure out what's going on.

Suggesting to wrap your connection factory with CachingConnectionFactory decorator and configure the session caching strategy:

<bean id="cacheConnFactory"
    class="org.springframework.jms.connection.CachingConnectionFactory">
    <property name="targetConnectionFactory" ref="connectionFactory" />
    <property name="cacheProducers" value="true" />
    <property name="cacheConsumers" value="true" />
    <property name="sessionCacheSize" value="10" />
</bean>

Use the above connection factory in your DMLC along with cacheLevel settings as follows:

<bean id="adp1Container"
    class="org.springframework.jms.listener.DefaultMessageListenerContainer"
    p:taskExecutor-ref="taskExecutor"
    p:destinationName="requestQueue1"
    p:connectionFactory-ref="cacheConnFactory"
    p:destinationResolver-ref="jmsDestinationResolver"
    p:transactionManager-ref="transactionManager">
    <property name="sessionTransacted" value="true" />
    <property name="cacheLevel" value="3" /> <!-- Consumer Level -->
</bean>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM