我们有一个基本的适配器=>通道=>带有int-jms:message-driven-channel-adapter
和int-jms:outbound-channel-adapter
的适配器模式。连接工厂是一个com.ibm.mq.jms.MQConnectionFactory
(下面的代码)。它从 MQSeries 代理 (9+) 获取发送到另一个 MQSeries 代理 (6+) 的消息。
此桥适用于我们的大多数收件人,但其中一个遇到了问题。当网桥在一段时间内不处于活动状态时,连接将变为"无效",一旦新消息到达,网桥将无法发送它。据我介绍,connectionFactory 的默认行为是在检测到出站已断开连接后立即重新连接。在这里,它没有检测到"断开连接",而是尝试使用以前的连接并失败:
Caused by: javax.jms.JMSException: MQJMS2007: failed to send message to MQ queue....
Caused by: com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2009'.
我不擅长网络/套接字(等等),但听起来接收方的东西已经过期(没有断开连接通知)。听起来连接上的"keepalive"选项在这里会有所帮助,但我无法在 Spring Integration JMS 和/或 IBM MQ 类中找到这样的机制。
有没有人知道我如何从弹簧集成方面执行这样的保持活动?或者关于为什么此连接过期而不通知的想法?
<beans>
<int:channel id="channelMQ_MQ" ></int:channel>
<!-- Source : MQseries -->
<!-- ... -->
<!-- Destination MQ_SERIES -->
<!- ... -->
<bean id="jmsQueueOut" class="com.ibm.mq.jms.MQQueue" depends-on="jmsConnectionFactory">
...
</bean>
<bean id="jmsConnectionFactory2" class="com.ibm.mq.jms.MQConnectionFactory">
<property name="queueManager" value="..." />
<property name="connectionNameList" value="..." />
<property name="channel" value="..." />
<property name="transportType" value="1" />
</bean>
<bean id="jmsConnectionFactory_cred2"
class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory" ref="jmsConnectionFactory2" />
<property name="username" value="..."/>
<property name="password" value="..."/>
</bean>
<bean id="connectionFactoryCaching2"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="jmsConnectionFactory_cred2" />
<property name="sessionCacheSize" value="..." />
</bean>
<int-jms:outbound-channel-adapter channel="channelMQ_MQ"
id="jmsOut"
destination="jmsQueueOut"
connection-factory="connectionFactoryCaching2"
delivery-persistent="true"
explicit-qos-enabled="true"
session-transacted="true" >
</int-jms:outbound-channel-adapter>
</beans>
编辑 1:
- MQSeries 版本 6
- IBM Mq 类 : 9.1.5
- 弹簧集成 : 5.5.13
- MQSeries 设置 :
- HBINT : 60
- 凯恩特 : 120
- SHARECNV => 在版本 6 上不存在
我们花了一点时间才找到这个技巧,但我们最终找到了合适的解决方案......
您需要在系统和应用程序端进行设置:
(在docker-compose中,需要使用 "systctls 子句")
系统:
- net.ipv4.tcp_keepalive_intvl=30
- net.ipv4.tcp_keepalive_probes=2
- net.ipv4.tcp_keepalive_time=60
应用
System.setProperty("com.ibm.mq.cfg.TCP.KeepAlive","YES");
(有多种方法可以设置此系统变量。这只是其中之一,例如)