Spring Boot JavaFX应用休眠后IBM MQ JMS重连失败求助
问题描述
我开发了一个Spring Boot JavaFX胖客户端应用,通过Spring Boot JMS(JmsTemplate,由Spring Boot自动配置)连接IBM MQ。已在application.properties中配置如下:
ibm.mq.queueManager = queuemanager ibm.mq.channel = channel I am using ibm.mq.connName = server to connect to ibm.mq.user = user name ibm.mq.password= the password ibm.mq.queue = the queue to use ibm.mq.reconnect=QMGR
应用启动时的跟踪日志如下:
2024-01-25 11:48:17:151 TRACE c.i.m.s.b.MQConfigurationProperties - constructor 2024-01-25 11:48:17:161 TRACE c.i.m.s.b.MQConnectionFactoryConfiguration - Creating caching MQConnectionFactory 2024-01-25 11:48:17:163 TRACE c.i.m.s.b.MQConnectionFactoryFactory - constructor 2024-01-25 11:48:17:163 TRACE c.i.m.s.b.MQConnectionFactoryFactory - createConnectionFactory for class MQConnectionFactory 2024-01-25 11:48:17:163 TRACE c.i.m.s.b.MQConfigurationSslBundles - SSLBundles are not supported 2024-01-25 11:48:17:163 TRACE c.i.m.s.b.MQConnectionFactoryFactory - configuring TLS Store system properties 2024-01-25 11:48:17:163 TRACE c.i.m.s.b.MQConnectionFactoryFactory - createConnectionFactoryInstance for class MQConnectionFactory 2024-01-25 11:48:17:342 TRACE c.i.m.s.b.MQConnectionFactoryFactory - configureConnectionFactory 2024-01-25 11:48:17:342 TRACE c.i.m.s.b.MQConfigurationProperties - queueManager : XX_XXX_X 2024-01-25 11:48:17:342 TRACE c.i.m.s.b.MQConfigurationProperties - applicationName : null 2024-01-25 11:48:17:342 TRACE c.i.m.s.b.MQConfigurationProperties - ccdtUrl : null 2024-01-25 11:48:17:342 TRACE c.i.m.s.b.MQConfigurationProperties - channel : THE_CHANNEL 2024-01-25 11:48:17:342 TRACE c.i.m.s.b.MQConfigurationProperties - clientId : null 2024-01-25 11:48:17:342 TRACE c.i.m.s.b.MQConfigurationProperties - connName : THE_MQ_SERVER 2024-01-25 11:48:17:342 TRACE c.i.m.s.b.MQConfigurationProperties - reconnectOption : 'QMGR' [0x04000000] 2024-01-25 11:48:17:342 TRACE c.i.m.s.b.MQConfigurationProperties - sslCipherSpec : null 2024-01-25 11:48:17:342 TRACE c.i.m.s.b.MQConfigurationProperties - sslCipherSuite : null 2024-01-25 11:48:17:342 TRACE c.i.m.s.b.MQConfigurationProperties - sslKeyresetcount: -1 2024-01-25 11:48:17:342 TRACE c.i.m.s.b.MQConfigurationProperties - sslPeerName : null 2024-01-25 11:48:17:342 TRACE c.i.m.s.b.MQConfigurationProperties - sslBundle : null 2024-01-25 11:48:17:342 TRACE c.i.m.s.b.MQConfigurationProperties - tempModel : null 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - tempQPrefix : null 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - tempTopicPrefix : null 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - user : 'XXXXXX' 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - password set : YES 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - sslFIPSRequired : false 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - useIBMCipherMappings : true 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - userAuthenticationMQCSP: true 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - outboundSNI : '' 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - channelSharing : '' 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - balancingAppType : '' [0] 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - balancingTimeout : '' [-1] 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - balancingOptions : '' [0] 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - jndiCF : null 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - jndiProviderUrl : null 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - JKS keystore : null 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - JKS keystore pw set : NO 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - JKS truststore : null 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - JKS truststore pw set : NO 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - No additional properties defined 2024-01-25 11:48:17:343 TRACE c.i.m.s.b.MQConfigurationProperties - Pooling is disabled
应用运行状态一切正常,但部分用户在不关闭应用的情况下合上笔记本盖子(应用进入休眠状态),再次打开笔记本继续使用时,重连失败。日志中报错如下:
nested exception is com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2556' ('MQRC_RECONNECT_TIMED_OUT').
目前只能通过重启应用恢复正常,请问我遗漏了哪些配置或有什么解决办法?
解决方案
一、补充IBM MQ重连核心配置
仅配置ibm.mq.reconnect=QMGR不足以应对休眠后网络恢复的延迟,需补充以下参数优化重连逻辑:
- 延长重连超时时间:添加
ibm.mq.reconnectTimeout=30(单位:秒),默认超时可能过短,导致网络未完全恢复时重连失败。 - 启用无限重连尝试:添加
ibm.mq.reconnectRetryCount=-1,设置为-1表示无限制重试,避免因有限次数耗尽导致重连终止。 - 配置重连间隔:添加
ibm.mq.reconnectRetryInterval=5(单位:秒),避免短时间内频繁重试浪费资源。
更新后的application.properties相关配置:
ibm.mq.reconnect=QMGR ibm.mq.reconnectTimeout=30 ibm.mq.reconnectRetryCount=-1 ibm.mq.reconnectRetryInterval=5
二、启用并配置JMS连接池
启动日志显示Pooling is disabled,未启用连接池时,休眠后的旧连接无法被自动回收重建。建议启用连接池:
- 添加连接池依赖(若未添加)
<dependency> <groupId>org.messaginghub</groupId> <artifactId>pooled-jms</artifactId> </dependency>
- 配置连接池参数
spring.jms.pool.enabled=true spring.jms.pool.max-connections=10 spring.jms.pool.idle-timeout=30000 spring.jms.pool.connection-timeout=60000
enabled=true:开启连接池idle-timeout:空闲连接30秒后自动销毁,避免持有无效连接connection-timeout:获取连接超时时间设为60秒,给重连留足时间
三、监听系统唤醒事件,主动重建连接
JavaFX应用可监听系统休眠/唤醒事件,在唤醒时主动重置JMS连接:
import javafx.application.Application; import javafx.application.Platform; import javafx.stage.Stage; import org.springframework.jms.core.JmsTemplate; import org.springframework.jms.connection.CachingConnectionFactory; import javax.jms.JmsException; public class MainApp extends Application { private JmsTemplate jmsTemplate; private CachingConnectionFactory connectionFactory; // 假设通过Spring注入jmsTemplate和connectionFactory @Override public void start(Stage primaryStage) { // 注册系统唤醒监听器(依赖AWT) try { System.setProperty("java.awt.headless", "false"); java.awt.SystemTray.getSystemTray().add(new java.awt.TrayIcon(new java.awt.ImageIcon("").getImage()) { @Override public void mouseClicked(java.awt.event.MouseEvent e) { // 系统唤醒时触发连接重建 Platform.runLater(MainApp.this::rebuildJmsConnection); } }); } catch (Exception e) { e.printStackTrace(); } } private void rebuildJmsConnection() { try { // 重置旧连接 connectionFactory.resetConnection(); // 测试新连接有效性 jmsTemplate.execute(session -> { session.createQueue(jmsTemplate.getDefaultDestinationName()); return null; }); } catch (JmsException e) { e.printStackTrace(); // 可添加重试逻辑 } } }
四、捕获重连异常并手动重试
在消息发送/接收逻辑中,针对MQRC_RECONNECT_TIMED_OUT(2556)异常添加重试机制:
public void sendMessage(String content) { int maxRetries = 3; int currentRetry = 0; while (currentRetry < maxRetries) { try { jmsTemplate.convertAndSend(content); return; } catch (JmsException e) { if (e.getCause() instanceof com.ibm.mq.MQException) { com.ibm.mq.MQException mqEx = (com.ibm.mq.MQException) e.getCause(); if (mqEx.getReason() == 2556) { currentRetry++; try { Thread.sleep(2000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } } else { throw e; } } else { throw e; } } } throw new RuntimeException("MQ重连失败,已达最大重试次数"); }
五、检查MQ服务器端配置
确认服务器端允许重连:
- 队列管理器的
RECONNECT属性需设为ENABLED - 通道的
SHARECNV参数避免设置过高,防止通道共享导致重连冲突 - 服务器端未限制客户端连接超时时间或次数
内容的提问来源于stack exchange,提问作者Willem
相关产品推荐
相关产品推荐

