🐇 RabbitMQ 内存告警排查

2026-9-8|2026-9-8
麦兜
麦兜
整理:由OpenAI GPT-5(Codex)发布。

问题

线上 RabbitMQ 突然出现内存告警,rabbitmq-diagnostics status 显示:
机器有 30 GiB 内存,当时操作系统仍有约 16 GiB available,但是 RabbitMQ 的内存高水位配置为 1.6106 GB。
这里的 vm_memory_high_watermark 是 RabbitMQ 的内存告警阈值。进程内存超过该值后会触发 Memory Alarm,并对消息发布端进行流控。它可以配置为相对值,也可以直接配置绝对值:
本次节点使用 rss 作为计算策略,因此告警判断主要看 RabbitMQ 进程的常驻内存。官方说明可以参考 Memory Threshold and Limit

排查

首先查看 RabbitMQ 的内存分类:
其中主要数据为:
binary 是 Erlang Runtime 的 binary heap 分类,通常会包含消息体、属性和网络数据相关的二进制对象;allocated_unused 是 Runtime 已经分配但当前没有使用的内存;连接、队列、消息索引和管理插件则会分别统计在其他分类中。各分类含义可以参考 RabbitMQ 官方的 Reasoning About Memory Use
继续使用 recon_alloc 查看 Erlang allocator:
得到的主要结果是:
allocator 数据是 Erlang 内存分配器管理的 carrier 和 block 口径,RabbitMQ 当前告警使用的是 RSS 口径,所以继续查看进程实际驻留内存:
结果为:
VmRSS 大约为 1.59 GiB,与 RabbitMQ 上报的 Total memory used 基本对应,并且已经超过 1.5 GiB 左右的高水位,所以 Memory Alarm 的触发是符合当前配置的。
接着看 memory breakdown 中的队列相关数据,queue_procs 只有几 MB,msg_index 也很低,没有体现出同等量级的队列内存。此时连接数为 1143,Socket 数为 1143,连接数量更值得继续拆分。
使用下面的命令按客户端来源聚合连接:
结果显示,某一个脱敏后的内网来源持有 993 条连接,其他来源大多数只有个位数或十位数。再查看连接详情:
根据来源地址定位到对应的数据服务。重启该服务后,RabbitMQ 上来自该来源的连接数量明显减少,同时内存也开始回落,因此可以确认这些连接由该服务持有。
但是重启只能确认连接归属,接下来还需要看为什么连接会一直增加。RabbitMQ Java Client 中 Connection 是物理 TCP 连接,Channel 是复用在 Connection 上的逻辑通道。官方建议 Connection 和 Channel 都应该长时间复用,相关生命周期说明见 Java Client API Guide

总结

这次排查主要由下面几条证据串起来:
  1. RabbitMQ 使用 RSS 计算内存,进程 VmRSS 已经超过 vm_memory_high_watermark
  1. 队列进程和消息索引占用较低,没有对应规模的队列内存增长。
  1. 1143 条连接中,有 993 条集中来自同一个客户端来源。
  1. 重启对应服务后,该来源连接数和 RabbitMQ 内存同步下降。
  1. 两个消费者每分钟执行一次恢复,八小时理论新增约 960 条连接,与现场数量基本一致。
  1. 代码调用链中存在周期性创建新 Connection、但旧 Connection 生命周期不完整的路径。
最终定位为客户端 Connection 持续累积导致 RabbitMQ RSS 上涨,并在超过配置的内存高水位后触发告警。
 
记一次生产环境接口返回时长异常排查Paul Graham|如何获得创业点子:摘要与案例
Loading...