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

ActiveMQ Artemis老年代内存上涨致性能下降问题排查咨询

问题背景

我开发了一个简化版的消息收发应用,通过以下路由实现:

  • 向http://0.0.0.0:8089/put-message发送HTTP请求时,会将JMS消息发送至my-queue;
  • 向http://0.0.0.0:8089/get-message发送HTTP请求时,Camel会尝试从my-queue消费JMS消息并将消息体返回给HTTP客户端。

蓝图配置文件

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
    <bean id="artemisConnectionFactory" class="org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory">
        <argument index="0" value="${jms.url}"/>
        <argument index="1" value="${jms.username}"/>
        <argument index="2" value="${jms.password}"/>
    </bean>

    <bean id="pooledConnectionFactory" class="org.messaginghub.pooled.jms.JmsPoolConnectionFactory"
          init-method="start" destroy-method="stop">
        <property name="maxConnections" value="10"/>
        <property name="maxSessionsPerConnection" value="500"/>
        <property name="connectionFactory" ref="artemisConnectionFactory"/>
    </bean>

    <bean id="jms" class="org.apache.camel.component.jms.JmsComponent">
        <property name="connectionFactory" ref="pooledConnectionFactory"/>
    </bean>

    <camelContext xmlns="http://camel.apache.org/schema/blueprint">
        <route>
            <from uri="jetty:http://0.0.0.0:8089/put-message"/>
            <inOnly uri="jms:my-queue"/>
        </route>
        <route >
            <from uri="jetty:http://0.0.0.0:8089/get-message"/>
            <pollEnrich timeout="0">
                <simple>jms:queue:my-queue</simple>
            </pollEnrich>
        </route>
    </camelContext>
</blueprint>

技术栈版本

  • ActiveMQ Artemis 2.25
  • Camel 2.23.2
  • Karaf 4.2
  • messaginghub/pooled-jms 1.0.6
  • artemis-jms-client-osgi 2.7.0

压测现象

使用Apache Bench进行压测(消息大小5KB,100个线程发送消息、100个线程接收消息),观察到以下现象:

  • 服务前半小时运行正常(队列长度无增长),但之后消息接收耗时逐渐增加;
  • 监控显示老年代(oldGen)内存持续上涨,且队列尚未进入分页(PAGE)模式;
  • 已按照ActiveMQ Artemis调优文档建议,在启动Broker时使用XX:+UseParallelOldGC垃圾收集器,但更换其他GC模式后现象仍未改变;
  • 若使用永久消费者(即配置<from uri="jms:queue:my-queue" />,不重新创建连接),服务运行稳定。

监控与更新信息

  • 监控截图显示:老年代内存持续上涨无回落,pollEnrich处理耗时随时间逐步升高;
  • 性能下降时的堆转储显示:内存中堆积了大量JMS会话、连接相关对象;
  • 使用官方性能工具测试./artemis perf client --message-size 5000 --persistent queue://TEST_QUEUE时,无内存泄漏现象。

问题

  1. 老年代内存持续上涨的原因可能是什么?
  2. 还可采集哪些指标以排查该问题?

解答

1. 老年代内存持续上涨的可能原因

(1)临时消费者/会话未正确回收

pollEnrich每次处理HTTP请求时都会创建临时JMS消费者拉取消息,结合Camel 2.23.2版本的实现,可能存在会话、消费者对象未正确归还给连接池的问题。大量临时对象在年轻代GC中无法被完全回收,逐渐晋升到老年代,导致内存持续上涨;同时,创建新会话/消费者的耗时增加,直接拉高pollEnrich的整体响应时间。而永久消费者模式下,消费者长期复用,不会频繁创建销毁对象,因此内存稳定。

(2)客户端与服务端版本不兼容

artemis-jms-client-osgi 2.7.0与ActiveMQ Artemis 2.25版本差距过大,跨大版本的客户端和服务端交互可能存在协议层面的对象泄漏,比如连接元数据、消息处理上下文无法被正确释放,长期堆积在老年代。

(3)连接池配置与并发不匹配

当前连接池maxConnections=10、maxSessionsPerConnection=500,但100个并发接收线程可能导致会话池被占满,后续请求需要创建新的会话甚至连接,大量短生命周期的连接/会话对象无法及时回收,进入老年代。

2. 可采集的排查指标

  • 连接池核心指标:采集activeConnections、idleConnections、activeSessions、idleSessions的实时数量,查看是否存在会话/连接无法回收、池资源耗尽的情况;
  • GC详细日志:开启-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC,分析YGC和Full GC的频率、每次GC回收的对象类型,确认老年代中堆积的对象具体类型;
  • Camel路由指标:采集pollEnrich节点的调用次数、平均耗时、异常次数,以及JMS组件的producerCount、consumerCount变化趋势;
  • Broker端连接会话指标:在Artemis控制台查看client-sessions、client-consumers的数量变化,确认是否存在大量未关闭的会话/消费者;
  • 线程栈快照:当性能下降时,抓取线程栈,查看是否有大量线程阻塞在JMS连接/会话创建、消息拉取环节;
  • 对象分配采样:使用jmap -histo:live或AsyncProfiler,采样内存中占比最高的对象类型,精准定位泄漏源头。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 20:55:22