It is mentioned in the documentation of DefaultMessageListenerContainer
class that it is not recommended to use CachingConnectionFactory
with dynamic scaling. While searching, I have encountered following link:
Why DefaultMessageListenerContainer should not use CachingConnectionFactory?
Here found a comment from Gary Russell that
the problem is with caching consumers when using variable concurrency in the container; we can end up with a live consumer "stuck" in the cache".
We have used DefaultMessageListenerContainer
and CachingConnectionFactory
together so this is surely a problem from above link.
We are encountering problems with our application having following behaviour:
- TCP ZeroWindow network congestion
- TCP RESET from application server to MQ
- DB connection grows during the issue while different transactions halt
- Messages in certain queues gets built up
We have following code configuration :
In ibmmq-context.xml file:
<!-- WebSphere MQ Connection Factory --> <bean id="appMqConnectionFactory" class="com.ibm.mq.jms.MQConnectionFactory"> <property name="hostName"> <value>${ibmmq.ip}</value> </property> <property name="port"> <value>${ibmmq.port}</value> </property> <property name="queueManager"> <value>${ibmmq.queuemanager}</value> </property> <property name="channel"> <value>${ibmmq.channel}</value> </property> <property name="clientReconnectOptions"> <util:constant static-field="com.ibm.msg.client.wmq.WMQConstants.WMQ_CLIENT_RECONNECT"/> </property> <property name="transportType" ref="appTransport"/> </bean> <!-- A cached connection --> <bean id="appCachedConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory"> <property name="targetConnectionFactory" ref="appMqConnectionFactory"/> <property name="sessionCacheSize" value="${jms.session.cachesize}"/> </bean> <!-- Use native MQ classes. --> <bean id="appTransport" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"> <property name="staticField"> <value>com.ibm.mq.jms.JMSC.MQJMS_TP_CLIENT_MQ_TCPIP</value> </property> </bean>
In jms-context file:
<bean id="bankListener" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref="cachedConnectionFactory" /> <property name="destination" ref="transactionResponseDestination" /> <property name="messageListener" ref="thirdpartyService" /> <property name="autoStartup" value="false"/> <property name="taskExecutor" ref="listenerExecutor"/> <property name="concurrency" value="20-30"/> </bean>
There are 6 such listeners like bankListener and each of the listeners has concurrency value, varies from 10-40
<bean id="listenerExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="maxPoolSize" value="140"/>
<property name="corePoolSize" value="100"/>
<property name="queueCapacity" value="30"/>
<property name="threadNamePrefix" value="jms-listener-task-"/>
<property name="threadGroupName" value="jms-listener-tasks"/>
</bean>
and jms-context.xml
file uses ibmmq-context.xml
file.
- And to note, we have used IBM MQ 7.1, Spring 4.2.8, spring-integration-core as 4.3.1.RELEASE and JBoss EAP 6.4.10
We are planning to fix this by following way:
<bean id="bankListener" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="appMqConnectionFactory" />
<property name="destination" ref="transactionResponseDestination" />
<property name="messageListener" ref="thirdpartyService" />
<property name="autoStartup" value="false"/>
<property name="taskExecutor" ref="listenerExecutor"/>
<property name="concurrency" value="20-30"/>
</bean>
My request:
Please review the configuration and let me know is there anything else to be changed.
Could you please also explain our application behaviour(above 4 points - a to d) with our current configuration with
CachingConnectionFactory
andDefaultMessageListenerContainer
Thanks in advance for your help.