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.0com.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
相关产品推荐
相关产品推荐

