RabbitMq消息阻塞,立即解决方案

如果目前你的 RabbitMQ 消费者 被卡住不再消费消息,且消息已经到达消费者绑定队列,但Spring Cloud Stream 没有继续触发 @StreamListener 的方法执行。这类问题一般是因为消费者线程阻塞消息被 RabbitMQ 拒绝投递。我们可以按照下面的步骤紧急处理:


✅ 立即解决方案(临时 + 快速恢复消费)

Step 1. 重启消费者服务

这一步是最快恢复消费的方式:

  • Spring Cloud Stream 的默认 ack 模式是自动 ack,只要没有抛出异常,MQ 就认为消费成功

  • 如果你遇到卡死,有可能是:

    • 前一条消息处理还没结束(线程阻塞)
    • 或者死循环/超时没释放线程
  • 重启服务可释放线程/消费挂起状态

# 假设是 docker 容器/服务
docker restart your-consumer-service
# 或者直接 kill 掉 Java 服务再启动

观察 RabbitMQ 管控台,看是否:

  • 队列消息数逐渐减少
  • 消费速率恢复为 > 0
  • 控制台中连接数和 channel 数重新建立

🔍 临时观察细节(可排查 root cause)

✅ RabbitMQ 控制台重点检查 3 项:

项目正常情况异常表现
Ready有新消息就增加,消费中就减少持续增长说明消息没人处理
Unacked一般在 0 ~ prefetch 区间内长期不变说明卡住未 ack
Consumer Utilization1.0小于 1.0 说明消费者阻塞或卡死

打开 RabbitMQ 中该 queue 的 “Consumer” 详情页,能看到具体的 Consumer 状态。


🔧 推荐补救优化(防止再次发生)

✅ 修改 application.yml 设置消费者并发 + prefetch:

spring:
  cloud:
    stream:
      bindings:
        executeAiBaseTask-in-0:
          destination: ai-paas-executeAiBaseTask.ai-platform
      rabbit:
        bindings:
          executeAiBaseTask-in-0:
            consumer:
              concurrency: 5       # 启动多个消费线程
              prefetch: 10         # 提前拉取多个消息处理
              acknowledge-mode: AUTO # 默认可以先用 AUTO,后面再换 MANUAL

✅ 改造处理逻辑为异步线程池提交:

@StreamListener(ExecuteAiBaseTaskBinding.INPUT)
public void executeAiBaseTask(String apiCode) {
    taskExecutor.submit(() -> handleAiTask(apiCode));
}

将你的整套复杂处理逻辑挪到 handleAiTask(apiCode) 中。


🛡️ 如果你急着排查是“哪条消息卡住了”

你可以尝试用 RabbitMQ 控制台 Web UI:

  • 在对应 Queue 上点击“Get messages

  • 获取队列中某些消息的 payload

  • 手动判断是否是某条任务数据异常

    • 比如 rightPop 之后无法解析 JSON、字段缺失、Redis 无响应等

总结

步骤目的操作
🔧 Step 1快速恢复消费重启消费服务
🔍 Step 2定位卡住原因RabbitMQ 控制台查看 Unacked 与队列状态
✅ Step 3防止再挂死增加并发、改异步处理、调高 prefetch
🛠 Step 4结构性优化异步线程池 + MANUAL ack 模式(推荐)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值