【问题标题】:JmsTemplate with CachingConnectionFactory Connection Recovery for IBM MQ Queue用于 IBM MQ 队列的具有 CachingConnectionFactory 连接恢复的 JmsTemplate
【发布时间】:2018-04-13 13:18:49
【问题描述】:

我正在使用 JmsTemplate 从同一个客户端连接到两个 IBM MQ 服务器。

我已经配置了 JmsTemplate 的 reconnectOnException 以及 IBM MQ 连接工厂的 setClientReconnectOptions。

Spring bean 定义:

<bean id="firstMQCachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
        <property name="targetConnectionFactory" ref="firstMQConnectionFactory" />
        <property name="sessionCacheSize" value="20" /> 
        <property name="reconnectOnException" value="true"/>
</bean>

<bean id="secondMQCachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
        <property name="targetConnectionFactory" ref="secondMQConnectionFactory" />
        <property name="sessionCacheSize" value="20" /> 
        <property name="reconnectOnException" value="true"/>
</bean>

设置 IBM MQ 重新连接选项:

firstMQConnectionFactory.setClientReconnectOptions(WMQConstancs.WMQ_CLIENT_RECONNECT;
firstMQConnectionFactory.setClientReconnectTimeout(5);
secondMQConnectionFactory.setClientReconnectOptions(WMQConstancs.WMQ_CLIENT_RECONNECT;
secondMQConnectionFactory.setClientReconnectTimeout(5);

这就是我发送消息的方式:

public boolean sendMsg(final String content) throws JmsException{
    boolean success = false;
    LOGGER.info("sendMsg: Start ") ;
    try { 
        jmsTemplate.send(new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                TextMessage textMessage = session.createTextMessage(content);
                textMessage.setStringProperty(WMQConstants.JMS_IBM_CHARACTER_SET,  "UTF8");
                textMessage.setIntProperty(WMQConstants.JMS_IBM_ENCODING,
                        WMQConstants.WMQ_ENCODING_NATIVE);
                textMessage.setJMSDeliveryMode(DeliveryMode.PERSISTENT);
                return textMessage;
            }
        });
        LOGGER.info("sendMsg: Message sent to MQ successfully");
        success = true;
    } catch (JmsException je) {
        LOGGER.error("sendMsg: JmsException " + je.getMessage());
        throw je;
    } catch (Exception exc) {
        LOGGER.error("sendMsg: Exception message: " + exc.getMessage());
        throw exc;
    }
    return success; 
}

当系统负载较低时没有使用任何连接时,Spring 会检测到与第一个系统的连接断开。

18 Nov 2017 20:41:03,924 WARN CachingConnectionFactory:322 - Encountered a JMSException - resetting the underlying JMS Connection
com.ibm.msg.client.jms.DetailedJMSException: JMSWMQ1107: A problem with this connection has occurred.
Caused by: com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2009' ('MQRC_CONNECTION_BROKEN').
18 Nov 2017 20:41:03,940 DEBUG CachingConnectionFactory:486 - Closing cached Session: com.ibm.mq.jms.MQQueueSession@4cbb56ac
18 Nov 2017 20:41:04,006 DEBUG CachingConnectionFactory:447 - Closing shared JMS Connection: com.ibm.mq.jms.MQQueueConnection@48d23557
18 Nov 2017 20:41:04,008 DEBUG CachingConnectionFactory:463 - Could not close shared JMS Connection
com.ibm.msg.client.jms.DetailedJMSException: JMSWMQ0019: Failed to disconnect from queue manager 'QM1' using connection mode '1' and host name 'system1.company.com(62305)'.
Caused by: com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2009' ('MQRC_CONNECTION_BROKEN').
Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2009;AMQ9208: Error on receive from host 'system1.company.com/10.0.0.1:62305 (system1.company.com)'. [1=-1,2=ffffffff,3=system1.company.com/10.0.0.1:62305 (system1.company.com),4=TCP]

这会以某种方式影响 JmsTemplate 与第二个系统的连接,并且在使用时我得到一个没有消息的异常。

18 Nov 2017 23:43:40,247 DEBUG JmsTemplate:482 - Executing callback on JMS Session: Cached JMS Session: com.ibm.mq.jms.MQQueueSession@5a4a62d0
18 Nov 2017 23:43:40,248 DEBUG JmsTemplate:595 - Sending created message: 
18 Nov 2017 23:43:40,251 ERROR MessageSender:86 - sendMsg: Exception message: null

堆栈跟踪

java.lang.NullPointerException
    at com.ibm.mq.jmqi.remote.impl.RemoteSession.checkIfDisconnected(RemoteSession.java:249)
    at com.ibm.mq.jmqi.remote.api.RemoteFAP.jmqiPutMessageWithProps(RemoteFAP.java:9045)
    at com.ibm.mq.jmqi.remote.api.RemoteFAP.jmqiPut(RemoteFAP.java:8115)
    at com.ibm.mq.ese.jmqi.InterceptedJmqiImpl.jmqiPut(InterceptedJmqiImpl.java:624)
    at com.ibm.mq.ese.jmqi.ESEJMQI.jmqiPut(ESEJMQI.java:635)
    at com.ibm.msg.client.wmq.internal.WMQMessageProducer$SpiIdentifiedProducerShadow.sendInternal(WMQMessageProducer.java:864)
    at com.ibm.msg.client.wmq.internal.WMQMessageProducer$ProducerShadow.send(WMQMessageProducer.java:548)
    at com.ibm.msg.client.wmq.internal.WMQMessageProducer.send(WMQMessageProducer.java:1393)
    at com.ibm.msg.client.jms.internal.JmsMessageProducerImpl.sendMessage(JmsMessageProducerImpl.java:851)
    at com.ibm.msg.client.jms.internal.JmsMessageProducerImpl.synchronousSendInternal(JmsMessageProducerImpl.java:2051)
    at com.ibm.msg.client.jms.internal.JmsMessageProducerImpl.sendInternal(JmsMessageProducerImpl.java:1989)
    at com.ibm.msg.client.jms.internal.JmsMessageProducerImpl.send(JmsMessageProducerImpl.java:1569)
    at com.ibm.mq.jms.MQMessageProducer.send(MQMessageProducer.java:321)
    at org.springframework.jms.connection.CachedMessageProducer.send(CachedMessageProducer.java:181)
    at sun.reflect.GeneratedMethodAccessor120.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.jms.connection.CachedMessageProducer$Jms2MessageProducerInvocationHandler.invoke(CachedMessageProducer.java:293)
    at com.sun.proxy.$Proxy59.send(Unknown Source)
    at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:626)
    at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:597)
    at org.springframework.jms.core.JmsTemplate$3.doInJms(JmsTemplate.java:562)
    at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:484)
    at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:559)
    at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:550)
  • 为什么一个 CachingConnectionFactory 的连接断开会影响 其他?
  • 为什么第二个连接不能从“异常”中恢复一次 它检测到它?
  • 是否需要在 JmsException 中包装 Exception 以便 spring jms 检测到它?

【问题讨论】:

  • >sendMsg: Exception message: null 我建议您打印完整的堆栈跟踪并编辑问题以添加它。

标签: java spring jms spring-jms jmstemplate


【解决方案1】:

我们可以通过更改网络连接来创建错误。

当 IBM MQ 客户端的重新连接打开并更改网络时,它会自动刷新后台连接。 Spring JMS 不会总是意识到这种刷新,并让我进入一个 CachingConnectionFactory 中的连接将被刷新但不会刷新其他状态的状态。

我通过不设置 setClientReconnectOptions 关闭了 IBM MQ 客户端重新连接,并让 spring 处理所有连接更改和问题。这修复了上述错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-07
    • 1970-01-01
    • 2018-01-22
    • 1970-01-01
    • 2017-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多