前面 25 篇拆的都是 RabbitMQ 的「机制」,这一篇转到「运维」——机制都懂了,线上出问题怎么定位和处理。

RabbitMQ 线上问题高度集中在三类:消息积压、publish 阻塞、连接泄漏。这三类占生产事故的绝大多数。它们的成因各不相同,但排查有一个共同的套路:先看指标定方向,再分层定位根因,最后对症处理。这一篇把这个闭环讲清楚。

先把监控指标建起来

排障的前提是有监控。RabbitMQ 要重点监控这几类指标:

队列健康:每个队列的消息数(ready + unacked)、入队速率、消费速率、消费者数。积压的本质是「入队速率 > 消费速率」,盯着这两个速率的差值能提前预警。

broker 资源:内存使用(对比 vm_memory_high_watermark)、磁盘剩余(对比 disk_free_limit)、文件描述符使用、Erlang 进程数。这些逼近上限都会触发流控或故障。

连接与信道:连接数、Channel 数、各连接的收发流量。连接数异常增长 = 泄漏;某个连接流量异常 = 可能在刷量或卡死。

集群状态:节点是否在线、分区告警、Quorum 队列的 leader 和副本同步状态。

这些指标 RabbitMQ 都通过管理插件(rabbitmq-management)的 HTTP API 暴露,可以对接 Prometheus + Grafana 做可视化告警。核心是给关键指标设阈值告警:积压超 N、内存超 80%、磁盘低于 2GB、消费者数为 0——这些都要主动告警,不能等用户报障才发现。

问题一:消息积压

现象:某个队列的 ready 消息数持续增长,消费速率跟不上入队速率。

排查方向(按可能性排序):

  1. 消费者挂了或变少。最常见原因。消费者进程崩溃、部署时被停、或健康检查失败被踢出。查队列的 consumer 数是否为 0 或骤降。处理:恢复消费者。

  2. 消费者处理变慢。消费者还在,但单条处理时间变长。原因可能是下游依赖变慢(数据库、第三方接口)、消费者机器负载高、或 GC 抖动。查消费者的处理耗时和下游依赖的响应时间。处理:优化处理逻辑、加消费者、或扩下游。

  3. 消费者 prefetch 设太大。前面讲过,prefetch 太大让消息全堆在消费者内存,broker 看不到真实消费能力。表现是 unacked 数很高但实际吞吐低。处理:调小 prefetch。

  4. 突发流量。入队速率突然飙升(秒杀、批量推送),超过消费者日常处理能力。处理:临时加消费者、或用 Quorum/惰性队列扛住积压。

  5. 毒丸消息卡住消费者。某条消息处理一直失败、无限重试,卡住整个消费。表现是消费停滞但消费者还在。处理:死信队列 + 重试次数限制,把毒丸消息转走。

积压的处理原则:先止血(加消费者、限流生产者),再治本(优化处理、扩容)。不要在积压时还让生产者全速写入,那样积压只会越来越深。

问题二:publish 阻塞

现象:生产者发不出消息,publish 操作卡住或报错。

排查方向

  1. 内存告警或磁盘告警。前面讲过,broker 内存超阈值或磁盘不足,会阻塞所有 publish。这是最常见原因。查 rabbitmqctl status 的 alarm 状态。处理:降内存(清积压、调内存阈值)、清磁盘。

  2. 流控(credit)。某个下游队列积压,credit 流控限流了生产者相关的连接。表现是 publish 变慢但没完全停。处理:解决下游积压。

  3. 网络问题。生产者和 broker 之间网络抖动、防火墙超时断连。表现是 publish 超时。处理:查网络、调心跳间隔。

  4. 连接被 block。broker 发了 connection.blocked 信号但客户端没正确处理,一直卡着。处理:客户端要响应 blocked/unblocked 信号,blocked 时暂停发送、unblocked 时恢复。

publish 阻塞的排查关键:先看是不是 broker 资源告警(全局问题),再看是不是单个队列积压引发的流控(局部问题)。全局告警影响所有生产者,局部流控只影响相关生产者,区分开才能定位。

问题三:连接泄漏

现象:broker 的连接数持续增长,不下降,最终耗光 fd 或内存。

排查方向

  1. 客户端没关连接/Channel。最常见。每处理一个请求就新建连接不复用,或者异常路径里忘了 close。查连接数趋势——如果随请求数线性增长,基本是泄漏。处理:修复客户端的连接管理,用连接池。

  2. 消费者反复重连。消费者因为某种原因(比如认证失败、队列不存在)不断断连重连,每次重连留下一堆僵尸连接。查日志里的连接建立/断开频率。处理:修复消费者的连接失败根因。

  3. 没有心跳,僵尸连接堆积。客户端崩溃但没正常断开 TCP,broker 侧连接还在(因为没心跳检测)。查那些「建立了但没流量」的连接。处理:开启心跳,让 broker 主动清理僵尸连接。

连接泄漏的处理:找到泄漏源(哪个客户端、哪种操作模式),修复它的连接生命周期管理。临时措施可以调大 broker 的连接数上限,但治本要靠客户端规范。监控上要设「连接数超过 N」的告警,在耗光资源前发现。

一个通用的排障闭环

把三类问题的排查收成一个通用闭环:

  1. 看告警和指标,定方向。积压看队列指标,阻塞看 broker 资源,泄漏看连接数。指标直接指向问题类别。
  2. 分层定位根因。生产端、broker 端、消费端、下游依赖,逐层排查。不要只看一端就下结论。
  3. 先止血再治本。止血(加消费者、限流、清理)保可用性,治本(优化代码、扩容、改配置)防复发。
  4. 复盘加监控。每次故障后,把「本次故障的早期指标」加进监控告警,下次类似问题能在恶化前发现。

这个闭环的关键是不靠猜,靠指标分层定位。RabbitMQ 的指标足够丰富,几乎所有问题都能从指标里找到线索,关键是排查者要熟悉「哪个指标对应哪类问题」。

积压、阻塞、连接泄漏的排查闭环

几个常被忽视的运维习惯

定期滚动重启。RabbitMQ 长期运行会有内存碎片,定期(比如每月)在集群模式下逐个重启节点,让 Erlang VM 回收内存。Quorum 保证滚动重启不影响服务。

关注 Erlang 层指标。除了业务指标,Erlang VM 的 scheduler 使用率、GC 时间、进程数也值得监控。Erlang 层的异常(比如某进程信箱爆炸)会表现为业务问题。

保留故障现场。故障发生时,先抓一份 rabbitmqctl statuslist_queueslist_connections 的快照,再处理。有了现场,事后复盘才有依据。

演练。定期演练 broker 故障切换、网络分区恢复、积压处理。不演练的预案,真出事时往往用不上。

收束:运维是机制理解的实战检验

这一篇没有新机制,全是前面 25 篇机制在运维场景的应用。能不能快速定位积压、阻塞、泄漏,直接检验对 prefetch、流控、连接模型的理解程度。运维能力 = 机制理解 + 排查套路 + 监控建设,三者缺一不可。

最后一篇是这个系列的收束——把 27 篇串成一张地图,回答「什么场景该用 RabbitMQ,怎么用」。


关于十三Tech

我是十三,All in AI Agent 方向的架构师,专注 AI 工程实践。我相信 AI 是程序员的最佳搭档。想跟完这套「图解 RabbitMQ」,欢迎关注公众号 「十三Tech」

十三Tech公众号二维码