彻底解决你 ActiveMQ CPU 飙高、假死、连接泄露、日志撑爆磁盘问题

张开发
2026/4/9 9:34:54 15 分钟阅读

分享文章

彻底解决你 ActiveMQ CPU 飙高、假死、连接泄露、日志撑爆磁盘问题
问题背景activemq运行一段时间后java进程达到300%而且一直居高不下这时很多消费端和生产端已经无法连接。运行环境java运行版本jdk-21_linux-x64_bin.tar.gzactivemq版本apache-activemq-6.0.1运行系统Centos7.9硬件4核8G你可能已经尝试过以下操作1、禁用 JDK21 虚拟线程根源 BUG导致 CPU 无限飙升2、替换 GC 为 G1解决 JDK21 默认 ZGC 高 CPU3、关闭 JMX 监控修复 ActiveMQ 6.0.1 线程泄漏4、优化 CentOS7 内核参数解决网络 IO 空转 CPU但问题已经并没有彻底解决以下才是真正彻底解决问题的兜底方案亲测有效彻底解决方案分4步全部执行一次根治彻底解决方案分4步全部执行一次根治第一步优化JVM参数核心解决CPU反复飙高之前的脚本仅配置了基础GC参数需补充「内存溢出、线程监控、GC日志」参数避免内存堆积和线程泄漏直接替换你ActiveMQ的bin/env文件中的JAVA_OPTS备份后修改。操作步骤进入ActiveMQ安装目录的bin文件夹cd 你的ActiveMQ路径/bin例如/opt/apache-activemq-6.0.1/bin备份原有env文件cp env env.bak.jvm区分之前的备份编辑env文件vim env删除原有JAVA_OPTS配置粘贴以下完整配置JAVA_OPTS-server \ -Djdk.virtualThreadScheduler.parallelism1 \ -Djdk.virtualThreadScheduler.maxPoolSize1 \ -Djava.util.concurrent.ForkJoinPool.common.parallelism1 \ # 优化GC保留原有配置补充日志适配8G内存 -XX:UseG1GC \ -XX:MaxGCPauseMillis200 \ -XX:PrintGCDetails \ -XX:PrintGCTimeStamps \ -XX:PrintHeapAtGC \ -XX:GCLogFileSize100m \ -XX:NumberOfGCLogFiles5 \ -Xloggc:${ACTIVEMQ_HOME}/logs/gc.log \ # 内存配置适配8G服务器保留原有Xms基础提升稳定性 -Xms1024m -Xmx2048m \ -Xmn1024m \ -XX:MetaspaceSize512m \ -XX:MaxMetaspaceSize1024m \ # 解决内存溢出、线程泄漏补充原有配置缺失项 -XX:HeapDumpOnOutOfMemoryError \ -XX:HeapDumpPath${ACTIVEMQ_HOME}/logs/heapdump.hprof \ -Dsun.net.client.defaultConnectTimeout10000 \ -Dsun.net.client.defaultReadTimeout30000 \ # 其他优化保留原有配置补充ActiveMQ必要参数 -Djava.net.preferIPv4Stacktrue \ -Dactivemq.temp.directory${ACTIVEMQ_HOME}/temp \ -Dactivemq.data${ACTIVEMQ_HOME}/data \$JAVA_OPTS关键说明该配置完全保留你原有env中的核心参数虚拟线程禁用、G1GC、基础内存配置仅做3点适配优化1. 适配8G服务器内存将Xmx提升至2048m2G、Xmn提升至1024mMetaspace参数同步扩容避免内存瓶颈2. 补充GC日志、内存溢出、线程泄漏相关参数方便后续排查3. 新增ActiveMQ临时目录、数据目录指定参数提升稳定性。日志会输出到ActiveMQ的logs目录不影响原有业务运行。第二步优化连接配置解决连接泄露、CPU空转你的openwire端口61616配置了最大连接数10000但未配置「连接超时回收」参数客户端断开后连接未释放导致连接堆积、CPU飙高需优化transportConnector配置仅修改openwire的uri其他端口不变。操作步骤继续编辑activemq.xml找到标签下的openwire配置将原有openwire的uri替换为以下内容新增连接回收、超时参数transportConnectornameopenwireuritcp://0.0.0.0:61616?maximumConnections10000amp;wireFormat.maxInactivityDuration600000amp;transport.keepalivetrueamp;keepAliveTime600000amp;transport.connectionTimeout30000amp;wireFormat.maxInactivityDurationInitalDelay30000amp;transport.closeAsynctrue/新增参数说明核心作用transport.connectionTimeout30000连接超时时间30秒避免无效连接占用资源wireFormat.maxInactivityDurationInitalDelay30000初始 inactive 检测延迟30秒快速识别无效连接transport.closeAsynctrue异步关闭无效连接避免阻塞线程降低CPU占用。注意其他端口amqp、stomp、mqttnio、ws无需修改保持原有配置即可。第三步添加监控自动恢复脚本兜底避免手动重启配置完成后添加一个定时监控脚本实时检测ActiveMQ的CPU占用和连接状态一旦CPU飙高超过80%或连接异常自动重启ActiveMQ无需手动干预彻底解决「重启才能恢复」的问题。推荐一起监控的核心指标最实用下面这些都是能真实反映 ActiveMQ 已经挂了 / 假死的指标而不是单纯看 CPU1. 端口监听是否存在61616现象进程还在但端口没监听 → 客户端连不上触发重启61616 端口消失2. Java 进程存在但不响应假死现象CPU 0% 或 100%但不处理消息、不响应连接触发重启连续多次无法获取 CPU / 进程异常3. 堆内存 OOM 前异常飙升现象内存一直涨、GC 疯狂跑触发重启堆内存使用率 90% 持续一段时间4. ActiveMQ 日志出现致命错误例如java.lang.OutOfMemoryError、KahaDB lock、IOException触发重启关键异常关键字出现5. 消息堆积严重生产不消费队列消息数暴增、消费停滞触发重启队列深度 阈值持续一段时间6. 文件句柄耗尽 / 连接数异常连接数爆了、句柄满了 → 不再接受新连接触发重启打开文件数 80% 限制操作步骤新建监控脚本vim /你的ActiveMQ路径/bin/monitor_activemq.sh粘贴以下脚本替换脚本中的「你的ActiveMQ路径」为实际路径#!/bin/bash# ActiveMQ 全能监控脚本# 监控CPU 内存 端口 FullGC 文件句柄AMQ_PATH你的ActiveMQ路径CPU_THRESHOLD85MEM_THRESHOLD90FD_PERCENT80FULLGC_COUNT_THRESHOLD10CHECK_INTERVAL60LOG_PATH${AMQ_PATH}/logs/monitor.log# 日志超过200M自动清空log(){[-f$LOG_PATH][$(du-b$LOG_PATH|awk{print $1})-ge209715200]$LOG_PATHecho[$(date%Y-%m-%d %H:%M:%S)]$1$LOG_PATH}# 进程是否存在is_running(){ps-ef|grep-Eactivemq.*java|grep-vgrep/dev/null21}# 获取PIDget_pid(){ps-ef|grep-Eactivemq.*java|grep-vgrep|awkNR1{print $2}}# 获取CPUget_cpu(){localpid$(get_pid)[-z$pid]echo0returntop-b-n1-p$pid|grep$pid|awk{print $9}|cut-d.-f1||echo0}# 获取内存get_mem(){localpid$(get_pid)[-z$pid]echo0returntop-b-n1-p$pid|grep$pid|awk{print $10}|cut-d.-f1||echo0}# 端口是否监听port_ok(){netstat-tuln|grep-w61616/dev/null21}# 获取文件句柄使用率%get_fd_usage(){localpid$(get_pid)[-z$pid]echo0returnlocalmax$(cat/proc/$pid/limits|grep-iopen files|awk{print $5})localused$(ls/proc/$pid/fd|wc-l)[$max-le0]echo0returnecho$((used*100/max))}# 获取FullGC次数jstatget_fullgc(){localpid$(get_pid)[-z$pid]echo0returnjstat-gc$pid|tail-n1|awk{print $8}||echo0}# 重启ActiveMQrestart_amq(){log 触发重启 ActiveMQ...$AMQ_PATH/bin/activemq stop/dev/null21sleep10localpid$(get_pid)[-n$pid]kill-9$pid/dev/null21sleep3$AMQ_PATH/bin/activemq start/dev/null21sleep10is_runninglog✅ 重启成功||log❌ 重启失败}# 连续告警计数ALERT_COUNT0LAST_FULLGC0log 全能监控已启动 whiletrue;doif!is_running;thenlog⚠️ 进程不存在重启restart_amqALERT_COUNT0sleep$CHECK_INTERVALcontinuefiif!port_ok;thenlog⚠️ 61616 端口丢失重启restart_amqALERT_COUNT0sleep$CHECK_INTERVALcontinuefiPID$(get_pid)CPU$(get_cpu)MEM$(get_mem)FD$(get_fd_usage)FULLGC$(get_fullgc)# 计算1分钟内新增FullGCif[$LAST_FULLGC-eq0];thenLAST_FULLGC$FULLGCfiFULLGC_INC$((FULLGC-LAST_FULLGC))LAST_FULLGC$FULLGClogCPU:${CPU}% MEM:${MEM}% FD:${FD}% FullGC:${FULLGC_INC}# 异常判断HIGH0[$CPU-ge$CPU_THRESHOLD]HIGH1[$MEM-ge$MEM_THRESHOLD]HIGH1[$FD-ge$FD_PERCENT]HIGH1[$FULLGC_INC-ge$FULLGC_COUNT_THRESHOLD]HIGH1if[$HIGH-eq1];thenALERT_COUNT$((ALERT_COUNT1))log⚠️ 第${ALERT_COUNT}/3 次异常else[$ALERT_COUNT-gt0]log✅ 恢复正常清空计数ALERT_COUNT0fi# 连续3次3分钟触发重启if[$ALERT_COUNT-ge3];thenlog 持续异常执行重启restart_amqALERT_COUNT0fisleep$CHECK_INTERVALdone第四步logrotate日志轮转长期管控推荐生产环境使用利用Linux系统自带的logrotate工具实现日志自动切割、压缩、保留历史日志、自动清理过期日志无需手动干预配置后永久生效符合Linux服务器日志管理最佳实践。操作步骤直接复制执行即可创建logrotate配置文件针对monitor.log单独配置vim /etc/logrotate.d/activemq_monitor粘贴以下配置适配你的monitor.log路径无需修改/opt/apache-activemq-6.0.1/logs/monitor.log {daily # 每日轮转1次rotate 7 # 保留7天的历史日志可调整如30保留30天compress # 对历史日志进行gzip压缩节省磁盘空间missingok # 若日志文件不存在不报错copytruncate # 轮转时不停止脚本避免监控中断关键notifempty # 日志为空时不进行轮转dateext # 历史日志文件名添加日期后缀如monitor.log-20260402maxsize 100M # 额外限制日志超过100MB立即轮转双重保障}保存退出按ESC输入:wq回车确认赋予配置文件正确权限避免logrotate无法读取chmod 644 /etc/logrotate.d/activemq_monitor测试配置是否生效模拟轮转不实际执行logrotate -d /etc/logrotate.d/activemq_monitor若输出无报错说明配置正常logrotate会通过系统crontab定时执行默认每天凌晨执行。1. 赋予脚本执行权限替换你自己的ActiveMQ路径实际路径直接复制执行chmod x /opt/apache-activemq-6.0.1/bin/monitor_activemq.sh2. 设置脚本后台常驻重启服务器后仍生效如果是修改先执行# 停止旧脚本ps -ef | grep monitor_activemq.sh | grep -v grep | awk ‘{print $2}’ | xargs kill -91. 编辑rc.localvim /etc/rc.d/rc.local2. 在文件末尾添加nohup /opt/apache-activemq-6.0.1/bin/monitor_activemq.sh3. 赋予rc.local执行权限chmod x /etc/rc.d/rc.local3. 启动监控脚本正确命令解决你遇到的提示nohup /opt/apache-activemq-6.0.1/bin/monitor_activemq.sh后台运行不会占用终端。脚本说明1每60秒检查一次CPU超过80%或61616端口异常2FullGC 频繁监控每 60 秒获取一次 FullGC 次数1 分钟内新增 ≥10 次 FullGC → 判定 GC 异常持续 3 分钟 → 重启2文件句柄FD监控获取进程最大允许打开文件数获取当前已使用句柄数使用率 ≥80% → 判定句柄即将耗尽持续 3 分钟 → 重启自动重启ActiveMQ日志记录在ActiveMQ的logs/monitor.log方便后续排查。CPU 内存 端口 GC 频繁 文件句柄溢出任意一项持续 3 分钟异常 → 自动重启。补充你执行脚本时的提示说明正常现象无需担心你执行命令nohup /opt/apache-activemq-6.0.1/bin/monitor_activemq.sh后出现nohup: ignoring input and appending output to ‘nohup.out’这是正常提示原因如下nohup 命令的作用是“忽略挂起信号让脚本后台运行”默认会将脚本的输出日志追加到当前目录的 nohup.out 文件中提示中“ignoring input”表示忽略终端输入不影响脚本运行“appending output to ‘nohup.out’”表示脚本输出原本应打印到终端的内容会写入 nohup.out 文件但我们的监控脚本已配置“日志写入 ActiveMQ 的 logs/monitor.log”因此 nohup.out 文件中几乎不会有内容无需关注该文件。核心问题你执行命令时缺少末尾的 符号导致脚本虽能后台运行但会触发 nohup 的默认输出提示且无法正常脱离终端。正确命令必须加上 即nohup /opt/apache-activemq-6.0.1/bin/monitor_activemq.sh执行后终端可正常操作脚本后台常驻。三、最终执行顺序必按此顺序确保生效停止ActiveMQ/opt/apache-activemq-6.0.1/bin/activemq stop执行第一步修改bin/env的JVM参数路径/opt/apache-activemq-6.0.1/bin/env执行第二步修改activemq.xml删除重复的managementContext路径/opt/apache-activemq-6.0.1/conf/activemq.xml执行第三步优化openwire的uri配置同第二步的activemq.xml文件执行第四步部署监控脚本并启动按上面的正确命令执行启动ActiveMQ/opt/apache-activemq-6.0.1/bin/activemq start查看启动状态/opt/apache-activemq-6.0.1/bin/activemq status确保启动成功。四、关键注意事项必看避免踩坑所有修改前务必备份配置文件env、activemq.xml避免误操作导致业务异常结合你的8G服务器内存JVM参数已优化为Xms1024m、Xmx2048m适配内存且保留原有Xms基础无需手动调整该配置能充分利用服务器内存提升ActiveMQ稳定性监控脚本已固定你的ActiveMQ路径/opt/apache-activemq-6.0.1无需再手动替换直接复制执行命令即可启动监控脚本时必须加上末尾的 符号否则会触发nohup提示且无法正常脱离终端修改完成后观察1-2小时查看logs目录下的gc.log和monitor.log确认无异常无需修改你的业务配置消息过期、死信队列、认证等所有优化均不影响业务正常运行。五、兜底排查若仍有异常执行此步骤若执行以上步骤后CPU仍偶尔飙高可查看日志排查具体原因查看GC日志tail -f /opt/apache-activemq-6.0.1/logs/gc.log排查是否有频繁GC、内存溢出查看监控日志tail -f /opt/apache-activemq-6.0.1/logs/monitor.log查看是否有自动重启记录查看ActiveMQ运行日志tail -f /opt/apache-activemq-6.0.1/logs/activemq.log排查是否有消息堆积、连接异常报错查看监控脚本运行状态ps -ef | grep monitor_activemq.sh若能看到脚本进程说明脚本正常运行若没有重新执行启动命令。按以上方案执行后可彻底解决「CPU反复飙高、连接异常、需手动重启」的问题无需再频繁重启ActiveMQ且完全贴合你的现有配置不影响业务运行。

更多文章