应用使用JMS连接池连接ActiveMQ Classic异常排查求助
JMS连接池与ActiveMQ Classic周期性无法发送消息问题排查
问题描述
应用采用JMS连接池与ActiveMQ Classic交互,启动初期运行正常,但运行数天后无法发送消息,重启应用后恢复正常,数天后问题再次出现。
- 初始错误:
com.thoughtworks.xstream.mapper.EnumMapper类找不到,引发XStream初始化异常; - 后续持续报错:无法连接到Broker URL,提示Web应用实例已停止,无法加载
org/apache/http/client/version.properties资源。
应用配置代码
public class ActiveMQConfig { private static final Logger logger = LoggerFactory.getLogger(ActiveMQConfig.class); // Active Mq properties @Value("${activeMQ.broker.url}") private String brokerUrl; @Value("${jms.listener.concurrency}") private String concurrency; // The duration between attempts to redliver a message @Value("${jms.rollback.redelivery.delay:10000}") private int redeliveryDelay; // Maximum number of times a redlivery of a message will be attempted -1 is infinite @Value("${jms.rollback.maximum.redeliveries:-1}") private String maximumRedelivery; @Value("${message.activeMQ.pool.max.connections:10}") private int activeMqPoolMaxConnections; @Bean public JmsListenerContainerFactory jmsListenerContainerFactory( @Qualifier("jmsConnectionFactoryActiveMQ") ConnectionFactory connectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer) { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConcurrency(concurrency); factory.setSessionTransacted(true); factory.setAutoStartup(false); factory.setErrorHandler(errorHandler -> logger.error("An error has occurred in the transaction: {}", errorHandler.getMessage())); configurer.configure(factory, connectionFactory); return factory; } @Bean @Primary public ActiveMQConnectionFactory jmsConnectionFactoryActiveMQ() { ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(); connectionFactory.setTrustAllPackages(true); // create re-delivery policy to configure re-attempt count and delay // when message is rolled back on queue in case of any exception RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy(); redeliveryPolicy.setMaximumRedeliveries(Integer.parseInt(maximumRedelivery)); redeliveryPolicy.setRedeliveryDelay(redeliveryDelay); connectionFactory.setRedeliveryPolicy(redeliveryPolicy); connectionFactory.setBrokerURL(brokerUrl); return connectionFactory; } @Bean public JmsTemplate jmsTemplateActiveMQ(PooledConnectionFactory pooledConnectionFactory) { JmsTemplate jmsTemplate = new JmsTemplate(); jmsTemplate.setPubSubDomain(false); jmsTemplate.setConnectionFactory(pooledConnectionFactory); return jmsTemplate; } @Bean public PooledConnectionFactory pooledConnectionFactory(ActiveMQConnectionFactory connectionFactory) { PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory(); pooledConnectionFactory.setConnectionFactory(connectionFactory); pooledConnectionFactory.setMaxConnections(activeMqPoolMaxConnections); return pooledConnectionFactory; } }
相关备注
activeMqPoolMaxConnections设置为10- 消息流入量为400-500条
- 使用
JMSXGroupID进行消息分组 - ActiveMQ连接URL为
https://dummy.dns.name.com/destination-name?useInactivityMonitor=false
原因分析
- 连接池资源耗尽:连接池最大连接数仅为10,结合
JMSXGroupID消息分组机制,同一分组的消息会绑定到同一个连接的会话中。若某分组的消息处理出现阻塞(如事务长时间未提交、消费逻辑卡顿),会持续占用该连接无法释放,最终导致连接池所有连接被占满,无法创建新连接发送消息。 - XStream依赖不兼容/缺失:
EnumMapper类找不到,说明项目中XStream的版本与ActiveMQ客户端依赖的版本冲突,或依赖包不完整。ActiveMQ客户端处理包含枚举类型的消息时需要XStream序列化,初始化失败会直接导致连接或会话创建异常。 - 连接失效无法感知:URL中禁用了
useInactivityMonitor,关闭了ActiveMQ默认的连接活跃度检测。当Broker与客户端的网络出现短暂中断或连接长期静默时,客户端无法察觉连接已失效,连接池中的僵死连接会被反复使用,引发连接失败。 - 类加载器异常:后续无法加载
org/apache/http/client/version.properties,说明应用运行一段时间后类加载器出现异常(如Web容器类加载器被回收、依赖包被意外卸载),导致HTTP客户端相关类无法加载,进而影响基于HTTPS协议的ActiveMQ连接。
解决方法
1. 优化连接池与消息分组配置
- 调整连接池参数:提升
activeMqPoolMaxConnections至20-30,同时设置闲置超时和连接验证逻辑,自动回收无效连接:@Bean public PooledConnectionFactory pooledConnectionFactory(ActiveMQConnectionFactory connectionFactory) { PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory(); pooledConnectionFactory.setConnectionFactory(connectionFactory); pooledConnectionFactory.setMaxConnections(activeMqPoolMaxConnections); pooledConnectionFactory.setIdleTimeout(30000); // 30秒闲置超时回收 pooledConnectionFactory.setTestOnBorrow(true); // 借连接时验证有效性 return pooledConnectionFactory; } - 优化消息分组处理:确保消费逻辑快速完成事务提交,避免长时间占用会话;若分组消息量过大,拆分分组数量,降低单连接的负载压力。
2. 修复XStream依赖问题
- 统一依赖版本:在项目依赖管理中明确指定与ActiveMQ客户端兼容的XStream版本(如ActiveMQ 5.16.x对应XStream 1.4.18),例如Maven配置:
<dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.18</version> </dependency> - 排除冲突依赖:通过Maven的
exclusions标签移除其他依赖中冲突的XStream版本,确保依赖一致性。
3. 恢复连接活跃度检测
- 移除URL中的
useInactivityMonitor=false参数,启用ActiveMQ默认的InactivityMonitor,让客户端自动检测并重建失效连接。 - 若因特殊需求必须禁用InactivityMonitor,需保留上述连接池的
setTestOnBorrow(true)配置,确保获取的连接都是可用状态。
4. 排查类加载器与内存问题
- 检查Web容器的类加载策略,禁止依赖包被意外卸载;确保Apache HttpClient的版本与ActiveMQ客户端兼容(ActiveMQ 5.x通常依赖HttpClient 4.5.x)。
- 使用内存分析工具(如MAT)检测应用内存泄漏点,若存在内存泄漏导致类加载器被回收,需修复泄漏问题(比如释放无用的对象引用、优化缓存逻辑)。
内容的提问来源于stack exchange,提问作者Prabhjot Sokhi
相关产品推荐
相关产品推荐

