ActiveMQ查堆积、怎么追踪原因、常用命令+告警模板

下面把 ActiveMQ(Classic 5.x) 单独补全:先讲它的死信队列机制、怎么查堆积、怎么追踪原因、常用命令+告警模板,最后和 Rabbit/Rocket/Kafka 做一句对比。


一、ActiveMQ 死信队列(DLQ)基础

1. 默认行为

  • 默认死信队列:ActiveMQ.DLQ(共享 DLQ)
  • 重试次数:默认 maxRedeliveries=6,超过就进 DLQ
  • 触发死信的场景:
    1. 消费者多次重试失败(>maxRedeliveries)
    2. 消息 TTL 过期
    3. 消息被消费者“毒信确认”(poison ACK)
    4. 事务回滚次数超限

2. 两种 DLQ 策略(生产必配)

在 activemq.xml 的 <destinationPolicy> 里配置:

(1)共享 DLQ(默认)

所有队列/topic 的死信都进 ActiveMQ.DLQ,不好排查。

<policyEntry queue=">">
  <deadLetterStrategy>
    <sharedDeadLetterStrategy/>
  </deadLetterStrategy>
</policyEntry>

(2)独立 DLQ(推荐)

每个业务队列对应一个 DLQ,格式:

  • Queue:ActiveMQ.DLQ.Queue.原队列名
  • Topic:ActiveMQ.DLQ.Topic.原topic名
<policyEntry queue=">">
  <deadLetterStrategy>
    <individualDeadLetterStrategy queuePrefix="DLQ."/>
  </deadLetterStrategy>
</policyEntry>

二、怎么检查 DLQ 有没有数据(3 种方法)

1. Web Console(最直观)

地址:http://MQ_IP:8161/admin

  1. 进入 Queues
  2. 找:
    • 共享:ActiveMQ.DLQ
    • 独立:DLQ.xxx 或 ActiveMQ.DLQ.Queue.xxx
  3. 看 Number Of Pending Messages > 0 就是有死信堆积

2. 命令行(Linux)

(1)查看所有队列及消息数

# 进入 ActiveMQ 安装目录
cd /usr/local/activemq/bin

# 查看队列列表+消息数
./activemq-admin query -Q | grep -E "Name|Pending"

(2)过滤 DLQ 队列

./activemq-admin query -Q | grep -E "DLQ|ActiveMQ.DLQ"

3. JMX 查看(运维监控常用)

  • MBean:org.apache.activemq:type=Broker,brokerName=*,destinationType=Queue,destinationName=ActiveMQ.DLQ
  • 指标:QueueSize(堆积数)

三、怎么追踪死信原因(关键属性)

1. 死信消息自带原因字段

消息属性里会有:

  • dlqDeliveryFailureCause:失败原因字符串(最关键)
  • redeliveryCounter:重试次数
  • originalDestination:原队列/topic
  • expiration:过期时间(如果是TTL死信)

常见 cause 内容:

  • Java.lang.Exception: 业务异常 → 消费者代码抛异常
  • Message expired → TTL 过期
  • Redelivery limit exceeded → 重试次数超限

2. Web Console 查看详情

  1. 进入 DLQ 队列 → Browse
  2. 点一条消息 → 看 Message Properties:
    • 重点复制 dlqDeliveryFailureCause 和 originalDestination
  3. 看 Body:消息体内容(JSON/文本)

3. 代码端查看(Java 示例)

while (true) {
    Message msg = consumer.receive();
    if (msg instanceof TextMessage) {
        TextMessage tm = (TextMessage) msg;
        // 死信原因
        String cause = tm.getStringProperty("dlqDeliveryFailureCause");
        // 原队列
        String origDest = tm.getStringProperty("originalDestination");
        // 重试次数
        int retry = tm.getIntProperty("redeliveryCounter");
        System.out.println("死信原因:" + cause);
    }
}

四、消息重放(修复后重新入队)

1. Web Console 一键移动(推荐)

  1. DLQ 队列 → Browse → 勾选消息
  2. 点 Move → 选择 Original Destination(原队列)→ 确认

2. 命令行重放

# 把 ActiveMQ.DLQ 的消息移到 ORDER.QUEUE
./activemq-admin move -b tcp://localhost:61616 \
  -q ActiveMQ.DLQ -d ORDER.QUEUE

五、告警配置模板

1. 监控指标

  • 指标:QueueSize(DLQ 队列待处理消息数)
  • 阈值:>0 即告警

2. 简易巡检脚本(crontab 1分钟)

#!/bin/bash
# activemq_dlq_check.sh
MQ_IP=127.0.0.1
DLQ_NAME=ActiveMQ.DLQ

# 获取 DLQ 消息数
COUNT=$(./activemq-admin query -Q -d $DLQ_NAME | grep Pending | awk '{print $NF}')

if [ $COUNT -gt 0 ];then
  echo "ActiveMQ 死信队列 $DLQ_NAME 堆积 $COUNT 条!"
  # 调用钉钉/企业微信告警接口
fi

3. Prometheus + Grafana 告警规则

groups:
- name: activemq_dlq
  rules:
  - alert: ActiveMQ_DLQ_Has_Messages
    expr: activemq_queue_size{destination=~".*DLQ.*"} > 0
    for: 10s
    labels:
      severity: error
    annotations:
      summary: "ActiveMQ 死信队列堆积"
      description: "队列:{{$labels.destination}},数量:{{$value}}"

六、四大 MQ 死信机制一句话对比

  • RabbitMQ:DLX+DLQ,靠 x-death 头看原因,UI 友好
  • RocketMQ:原生 %DLQ%+消费者组,消息轨迹最强,高并发首选
  • Kafka:无原生DLQ,业务自定义dlq-topic,靠Header+日志追踪
  • ActiveMQ:默认共享 ActiveMQ.DLQ,可配独立DLQ,原因在 dlqDeliveryFailureCause

ActiveMQ 速查清单(配置+命令+脚本+告警)

一、核心配置(activemq.xml 直接复制)

1. 推荐配置:独立死信队列(生产环境)

每个业务队列生成专属 DLQ,便于排查

<!-- 目的地策略:全局队列生效 -->
<destinationPolicy>
    <policyMap>
      <policyEntries>
        <!-- 匹配所有队列 -->
        <policyEntry queue=">">
          <!-- 死信策略:独立DLQ -->
          <deadLetterStrategy>
            <individualDeadLetterStrategy 
                queuePrefix="DLQ." 
                useQueueForQueueMessages="true"
                useTopicForTopicMessages="false"/>
          </deadLetterStrategy>
          <!-- 最大重发次数:默认6次,可自定义 -->
          <redeliveryPolicy>
            <redeliveryPolicy maximumRedeliveries="6"/>
          </redeliveryPolicy>
        </policyEntry>
      </policyEntries>
    </policyMap>
</destinationPolicy>

效果:原队列 ORDER_QUEUE → 死信队列 DLQ.ORDER_QUEUE

2. 默认配置:全局共享死信队列(不推荐排查)

所有消息失败统一进入 ActiveMQ.DLQ

<policyEntry queue=">">
  <deadLetterStrategy>
    <sharedDeadLetterStrategy/>
  </deadLetterStrategy>
</policyEntry>

3. 消息过期自动进DLQ(TTL 配合)

如需消息超时进入死信,开启全局TTL策略:

<policyEntry queue=">">
  <expirationMapCheckStyle>LAZY</expirationMapCheckStyle>
</policyEntry>

二、常用运维命令(进入 activemq/bin 目录执行)

基础环境

默认端口:

  • Web控制台:8161
  • TCP连接端口:61616

1. 启停服务

# 启动
./activemq start

# 停止
./activemq stop

# 重启
./activemq restart

# 查看状态
./activemq status

2. 查询队列/死信队列(核心排查)

# 查看所有队列 + 消息堆积数
./activemq-admin query -Q

# 只筛选所有 DLQ 死信队列
./activemq-admin query -Q | grep DLQ

# 查询指定单个死信队列详情
./activemq-admin query -Q -d DLQ.ORDER_QUEUE

3. 消息移动(死信重放,修复后使用)

# 将 DLQ 消息移动回原业务队列(通用格式)
./activemq-admin move \
-b tcp://127.0.0.1:61616 \
-q 死信队列名 \
-d 原业务队列名

# 示例:把 DLQ.ORDER_QUEUE 消息移回 ORDER_QUEUE
./activemq-admin move \
-b tcp://127.0.0.1:61616 \
-q DLQ.ORDER_QUEUE \
-d ORDER_QUEUE

4. 清空队列(谨慎!生产慎用)

# 清空指定队列所有消息
./activemq-admin purge -Q DLQ.ORDER_QUEUE

5. 查看连接、消费者

# 查看所有客户端连接
./activemq-admin connections

# 查看队列消费者
./activemq-admin consumers

三、Web 控制台操作(可视化排查)

访问地址:http://MQ_IP:8161/admin
默认账号密码:admin / admin

  1. 查看死信堆积
    左侧 → Queues → 找到 DLQ.xxx / ActiveMQ.DLQ
    查看字段:Number Of Pending Messages(待消费消息数)

  2. 查看死信详情&原因
    对应DLQ队列 → 点击 Browse → 选中消息

    • dlqDeliveryFailureCause:失败根因(重点)
    • redeliveryCounter:重试次数
    • originalDestination:来源队列
    • Message Body:原始消息内容
  3. Web端重放消息
    勾选消息 → 点击 Move → 选择原队列 → 提交


四、定时巡检脚本(Shell + Crontab)

脚本:activemq_dlq_check.sh

#!/bin/bash
# ActiveMQ 死信队列巡检脚本
MQ_BIN="/usr/local/activemq/bin"
# 替换为你的死信队列(多个用空格分隔)
DLQ_LIST="ActiveMQ.DLQ DLQ.ORDER_QUEUE DLQ.PAY_QUEUE"
MQ_URL="tcp://127.0.0.1:61616"

# 遍历所有死信队列
for dlq in $DLQ_LIST
do
  # 获取堆积消息数
  COUNT=$(${MQ_BIN}/activemq-admin query -Q -d ${dlq} 2>/dev/null | grep "Pending" | awk '{print $NF}')
  
  # 判断是否有堆积
  if [[ -n "$COUNT" && "$COUNT" -gt 0 ]]; then
    MSG="【告警】ActiveMQ 死信队列 ${dlq} 存在堆积,消息数:${COUNT}"
    echo ${MSG}
    # ========== 对接钉钉/企业微信机器人(自行替换URL)==========
    # curl -s "https://oapi.dingtalk.com/robot/send?access_token=XXX" \
    # -H "Content-Type: application/json" \
    # -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"${MSG}\"}}"
  fi
done

添加定时任务(1分钟巡检一次)

# 赋予执行权限
chmod +x /usr/local/script/activemq_dlq_check.sh

# 编辑定时任务
crontab -e

# 写入规则
*/1 * * * * /usr/local/script/activemq_dlq_check.sh >> /usr/local/script/activemq_dlq_log.log 2>&1

五、Prometheus + Grafana 告警规则

依赖:activemq-exporter 采集监控指标

groups:
- name: activemq_dlq_alerts
  rules:
  # 死信队列出现消息立即告警
  - alert: ActiveMQ_DLQ_Msg_Exists
    expr: activemq_queue_size{destination=~"DLQ.*|ActiveMQ.DLQ"} > 0
    for: 10s
    labels:
      severity: error
      service: activemq
    annotations:
      summary: "ActiveMQ 死信队列堆积告警"
      description: "队列名称:{{ $labels.destination }},当前堆积消息数:{{ $value }}"

六、常见死信原因速查表

异常字段内容 问题原因 处理方案
Redelivery limit exceeded 重试次数达到上限 排查消费者代码/依赖服务
Message expired 消息TTL超时未消费 调大TTL、提升消费能力
Java Exception/NullPoint 消费者代码抛异常 查看应用日志修复Bug
Transaction rolled back 事务多次回滚 检查数据库/事务逻辑

七、五大MQ死信机制极简汇总(背诵版)

  1. RabbitMQ:DLX交换机+DLQ队列,依靠 x-death 识别原因
  2. RocketMQ:原生 %DLQ%+消费组,消息轨迹完善,高并发首选
  3. Kafka:无原生死信,业务自建DLQ Topic,靠Header+日志排查
  4. ActiveMQ:默认ActiveMQ.DLQ,可配置独立DLQ,原因存 dlqDeliveryFailureCause
  5. 总结:业务系统优先 RocketMQ;传统老旧项目多见 ActiveMQ;大数据流用 Kafka;路由复杂选 RabbitMQ。
posted @ 2026-06-07 12:58  堭鍙銤  阅读(60)  评论(0)    收藏  举报