You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 2.7.x升级3.1.x后IBM MQ JMS客户端连接异常求助

Spring Boot 3.1.1 + IBM MQ Jakarta客户端连接失败(MQRC_CONNECTION_BROKEN)问题排查与解决

问题背景

将Spring Boot应用从2.7.8升级到3.1.1,同步升级mq-jms-spring-boot-starter至3.1.1,使用依赖:

  • com.ibm.mq:com.ibm.mq.jakarta.client:9.3.3.0
  • com.ibm.mq:mq-jms-spring-boot-starter:3.1.1
    Java版本为Amazon Correto 17.0.6,仅将所有JMS相关包切换至Jakarta命名空间,此前基于javax栈的版本与队列管理器交互正常,升级后发送消息时出现MQRC_CONNECTION_BROKEN(2009)错误。

现有配置代码

JmsConfig配置

private static final Integer SESSION_CACHE_SIZE = 500;

private final JMSProperties properties;

@Bean
public MQQueueConnectionFactory mqQueueConnectionFactory() {
    MQQueueConnectionFactory mqQueueConnectionFactory = new MQQueueConnectionFactory();
    try {
        mqQueueConnectionFactory.setHostName(properties.getHost());
        mqQueueConnectionFactory.setQueueManager(properties.getQueueManager());
        mqQueueConnectionFactory.setPort(properties.getPort());
        mqQueueConnectionFactory.setChannel(properties.getChannel());
        mqQueueConnectionFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
    } catch (Exception e) {
        throw new RuntimeException("Error occurred while creating connection factory", e);
    }
    return mqQueueConnectionFactory;
}

@Bean
public UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter(MQQueueConnectionFactory mqQueueConnectionFactory) {
    UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter = new UserCredentialsConnectionFactoryAdapter();
    userCredentialsConnectionFactoryAdapter.setTargetConnectionFactory(mqQueueConnectionFactory);
    userCredentialsConnectionFactoryAdapter.setUsername(properties.getUser());
    userCredentialsConnectionFactoryAdapter.setPassword(properties.getPassword());

    return userCredentialsConnectionFactoryAdapter;
}

@Bean
public CachingConnectionFactory cachingConnectionFactory(UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter) {
    CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
    cachingConnectionFactory.setTargetConnectionFactory(userCredentialsConnectionFactoryAdapter);
    cachingConnectionFactory.setSessionCacheSize(SESSION_CACHE_SIZE);
    cachingConnectionFactory.setCacheConsumers(false);
    cachingConnectionFactory.setCacheProducers(false);
    cachingConnectionFactory.setReconnectOnException(true);

    return cachingConnectionFactory;
}

@Bean
public JmsTemplate jmsTemplate(CachingConnectionFactory cachingConnectionFactory) {
    JmsTemplate template = new JmsTemplate(cachingConnectionFactory);
    template.setReceiveTimeout(properties.getReceiveTimeoutMs());
    return template;
}

@Bean
public Jaxb2Marshaller someMarshaller() {
    Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
    jaxb2Marshaller.setPackagesToScan("somePackages");
    jaxb2Marshaller.setMarshallerProperties(Map.of(JAXB_FORMATTED_OUTPUT, true));
    return jaxb2Marshaller;
}

导入的Jakarta包

import com.ibm.mq.jakarta.jms.MQQueueConnectionFactory; 
import com.ibm.msg.client.jakarta.wmq.WMQConstants; 
import static jakarta.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT;

消息发送代码

private final JmsTemplate jmsTemplate;

public void send(String queue, String message, String correlationId) {
    jmsTemplate.convertAndSend(queue, message, new CorrelationIdPostProcessor(correlationId));
}

private static class CorrelationIdPostProcessor implements MessagePostProcessor {
    private final String correlationId;

    CorrelationIdPostProcessor(String correlationId) {
        this.correlationId = correlationId;
    }

    public Message postProcessMessage(Message message) throws JMSException {
        message.setJMSCorrelationID(correlationId);

        return message;
    }
}

错误信息

org.springframework.jms.UncategorizedJmsException: Uncategorized exception occurred during JMS processing; 
  nested exception is com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2009' ('MQRC_CONNECTION_BROKEN')...

  Caused by: com.ibm.msg.client.jakarta.jms.DetailedJMSException: JMSWMQ0018: Failed to connect to queue manager 'WMB02PQM' with connection mode 'Client' and host name 'Client'....
  com.ibm.msg.client.jakarta.jms.admin.JmsConnectionFactoryImpl.createConnection(JmsConnectionFactoryImpl.java:242)
  com.ibm.mq.jakarta.jms.MQConnectionFactory.createCommonConnection(MQConnectionFactory.java:6026)
  com.ibm.mq.jakarta.jms.MQQueueConnectionFactory.createQueueConnection(MQQueueConnectionFactory.java:142)
  com.ibm.mq.jakarta.jms.MQQueueConnectionFactory.createConnection(MQQueueConnectionFactory.java:228)
  org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter.doCreateConnection(UserCredentialsConnectionFactoryAdapter.java:188)
  org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter.createConnection(UserCredentialsConnectionFactoryAdapter.java:162)
  org.springframework.jms.connection.SingleConnectionFactory.doCreateConnection(SingleConnectionFactory.java:427)
  org.springframework.jms.connection.SingleConnectionFactory.initConnection(SingleConnectionFactory.java:352)
  org.springframework.jms.connection.SingleConnectionFactory.getConnection(SingleConnectionFactory.java:327)
  org.springframework.jms.connection.SingleConnectionFactory.createConnection(SingleConnectionFactory.java:242)
  org.springframework.jms.support.JmsAccessor.createConnection(JmsAccessor.java:196)
  
  org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:497)
  Caused by: com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2009' ('MQRC_CONNECTION_BROKEN').
  
  com.ibm.msg.client.jakarta.wmq.common.internal.Reason.createException(Reason.java:203)
  Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2009;AMQ9204: Connection to host 'myQueueManagerAddress(port)' rejected. 
  [1=com.ibm.mq.jmqi.JmqiException[CC=2;RC=2009],3=myQueueManagerAddress(port),4=,5=RemoteConnection.asyncConnectionBroken]
  
  com.ibm.mq.jmqi.remote.api.RemoteFAP$Connector.jmqiConnect(RemoteFAP.java:13670)
  com.ibm.mq.jmqi.remote.api.RemoteFAP$Connector.access$100(RemoteFAP.java:13202)
  com.ibm.mq.jmqi.remote.api.RemoteFAP.jmqiConnect(RemoteFAP.java:1451)
  com.ibm.mq.jmqi.remote.api.RemoteFAP.jmqiConnect(RemoteFAP.java:1392)
  com.ibm.mq.ese.jmqi.InterceptedJmqiImpl.jmqiConnect(InterceptedJmqiImpl.java:377)
  com.ibm.mq.ese.jmqi.ESEJMQI.jmqiConnect(ESEJMQI.java:562)
  
  com.ibm.msg.client.jakarta.wmq.internal.WMQConnection.<init>(WMQConnection.java:391)
  Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2009

解决方案

1. 显式配置SSL/TLS参数

IBM MQ Jakarta客户端9.3.x版本可能默认启用了SSL/TLS连接,而此前的javax版本可能默认使用普通TCP。根据队列管理器的配置,调整以下参数:

  • 如果队列管理器未启用SSL,添加代码禁用SSL:
// 在mqQueueConnectionFactory()方法中添加
mqQueueConnectionFactory.setStringProperty(WMQConstants.WMQ_SSL_CIPHER_SUITE, "NONE");
  • 如果队列管理器启用了SSL,设置对应的Cipher Suite,例如:
mqQueueConnectionFactory.setStringProperty(WMQConstants.WMQ_SSL_CIPHER_SUITE, "TLS_RSA_WITH_AES_256_CBC_SHA256");

2. 验证连接模式与传输类型

确认WMQConstants.WMQ_CM_CLIENT在Jakarta版本中是否仍有效,可显式设置连接模式:

mqQueueConnectionFactory.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);

同时检查端口是否匹配:普通TCP默认1414,SSL默认1415,确保配置的端口与队列管理器一致。

3. 临时禁用连接缓存排查问题

CachingConnectionFactory的缓存机制可能在版本升级后导致连接兼容性问题,临时替换为普通ConnectionFactory或调整缓存参数:

// 替换CachingConnectionFactory为直接返回UserCredentialsConnectionFactoryAdapter
@Bean
public ConnectionFactory connectionFactory(UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter) {
    return userCredentialsConnectionFactoryAdapter;
}

// 调整JmsTemplate依赖
@Bean
public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) {
    JmsTemplate template = new JmsTemplate(connectionFactory);
    template.setReceiveTimeout(properties.getReceiveTimeoutMs());
    return template;
}

如果连接恢复正常,再逐步调整CachingConnectionFactory的参数,例如降低SESSION_CACHE_SIZE,或启用连接缓存时添加setCacheConnections(true)。

4. 排查依赖冲突

确保项目中没有残留的javax JMS或IBM MQ javax版本依赖,使用依赖分析工具检查:

  • Maven:mvn dependency:tree | grep javax
  • Gradle:./gradlew dependencies | grep javax
    排除所有javax相关的JMS依赖,确保仅使用Jakarta版本。

5. 启用详细日志定位问题

添加日志配置,开启IBM MQ客户端的DEBUG日志,查看更详细的连接失败细节:

# application.properties
logging.level.com.ibm.msg.client.jakarta.wmq=DEBUG
logging.level.com.ibm.mq.jakarta=DEBUG

日志会显示连接过程中的协议协商、SSL握手等细节,帮助定位具体失败原因。


内容的提问来源于stack exchange,提问作者Ubizza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 02:00:01