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

应用使用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

原因分析

  1. 连接池资源耗尽:连接池最大连接数仅为10,结合JMSXGroupID消息分组机制,同一分组的消息会绑定到同一个连接的会话中。若某分组的消息处理出现阻塞(如事务长时间未提交、消费逻辑卡顿),会持续占用该连接无法释放,最终导致连接池所有连接被占满,无法创建新连接发送消息。
  2. XStream依赖不兼容/缺失:EnumMapper类找不到,说明项目中XStream的版本与ActiveMQ客户端依赖的版本冲突,或依赖包不完整。ActiveMQ客户端处理包含枚举类型的消息时需要XStream序列化,初始化失败会直接导致连接或会话创建异常。
  3. 连接失效无法感知:URL中禁用了useInactivityMonitor,关闭了ActiveMQ默认的连接活跃度检测。当Broker与客户端的网络出现短暂中断或连接长期静默时,客户端无法察觉连接已失效,连接池中的僵死连接会被反复使用,引发连接失败。
  4. 类加载器异常:后续无法加载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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 00:01:04