bigywater.tech
RabbitMQ · 20

流控(flow control)与内存、磁盘水位告警

发布太快会把 broker 压垮吗?RabbitMQ 怎么让发布者慢下来?内存和磁盘水位线分别按什么口径,触发后客户端看到什么,消费者受不受影响?这篇把水位线调到刚好够用,真的压到告警并观察两侧的反应。

221 MiB
把水位线设成当前 RSS 181.7 MiB + 40 MiB;发布 48758 条后触发 Memory alarm
low on memory
pika 收到的 Connection.Blocked 原因
800 / 800
4 个发布连接 200 次采样全部是 running,没有观察到 flow

内存水位线与阻塞

实测 · 本机执行输出
  rabbitmqctl status 里的内存部分: Total memory used: 0.189 gb | Calculation strategy: rss | Memory high watermark setting: 0.6 of available memory, computed to: 0.6442 gb
  当前 broker 进程内存(RSS,告警比较的就是这个口径)约 181.7 MiB;$ rabbitmqctl set_vm_memory_high_watermark absolute 221MiB(当前 + 40 MiB)
  (秒, 已发条数, 内存 MiB) 的采样: [(0.2, 6291, 186.9), (0.8, 27247, 215.6), (1.5, 47052, 245.2), (2.1, 48758, 253.3), (2.3, 48758, 244.3)]
  发布线程停在 48758 条(之后不再前进);rabbitmq-diagnostics alarms:
    Asking node q20@localhost to report any known resource alarms ...
    Memory alarm on node q20@localhost
  list_connections 的 state: ['blocking', 'blocked']

vm_memory_high_watermark 默认是可用内存的 0.6,统计口径是进程 RSS。超过后 broker 触发内存告警,发布连接进入 blocking → blocked,不再读取它们的数据;客户端收到 Connection.Blocked,带原因 low on memory(pika 要在 process_data_events 里才会调用 blocked 回调)。

消费者与解除

实测 · 本机执行输出
  pika 回调记录: [('blocked', 'low on memory')]
  消费者运行中收到 Unblocked 的时刻(消费开始后秒数, 已消费条数, 内存 MiB): (1.3, 48051, 207.7)
  事件序列: ['blocked', 'unblocked'];发布线程之后又继续发了 69348 条(累计)

阻塞只针对发布连接。消费者继续工作,把消息读走、内存降下来,告警解除,发布连接收到 Connection.Unblocked。解除靠的是内存降下来,不是重启发布者。

磁盘水位线

实测 · 本机执行输出
  rabbitmqctl status 里的磁盘部分: Low free disk space watermark: 0.05 gb | Free disk space: (not available)
  broker 日志里关于磁盘监控的行:
    <0.791.0> Free disk space monitor encountered an error retrieving total memory. Retries left: 10 Error:
  操作系统 df 看到数据目录所在卷剩余 27.3 GiB;把 disk_free_limit 设成比它多 5 GiB 后等 15 秒,rabbitmq-diagnostics alarms:
    Asking node q20@localhost to report any known resource alarms ...
    Node q20@localhost reported no alarms, local or clusterwide
  这台 macOS 上 broker 读不到磁盘剩余空间(Free disk space: not available),磁盘告警在这里无法触发,所以这一节只能验证到这里

磁盘告警的机制与内存相同,但这台 macOS 上 broker 读不到磁盘剩余空间(Free disk space: not available),所以磁盘告警在这里没有验证。

信用流控

实测 · 本机执行输出
  200 次采样累计(每次采样 4 条发布连接 + 偶尔 CLI 连接)看到的 state: #{running => 800};这段时间共发布 90720 条

除了告警,连接和队列之间还有信用(credit)流控,过载时连接状态会显示 flow。这次 4 个全速发布者没有触发,需要队列跟不上的场景才能看到。

分步演示

流控与水位线
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / RabbitMQ 4.3.6 / Erlang/OTP 28.5 / pika 1.4.4(Homebrew 与临时虚拟环境);所有节点都是本机自己起的 RabbitMQ 进程(127.0.0.1,端口 9500 以上,每个实验独立的数据目录与节点名,不连任何外部服务);命令输出来自真实的 rabbitmqctl 与管理 API,发布与消费用 pika 的真实连接;计时用 time.perf_counter,数字每次运行会有小幅抖动。水位线用 rabbitmqctl set_vm_memory_high_watermark absolute 设置为“当前 RSS(ps)+ 40 MiB”;状态与告警来自 rabbitmqctl list_connections 与 rabbitmq-diagnostics alarms;pika 的 blocked / unblocked 回调在发布线程的 process_data_events 里触发;磁盘实验的 df 数字是 df -k 的剩余空间
    • 没有验证:磁盘告警本身(读不到剩余空间);flow 状态何时出现;集群里告警是全局的(一个节点超限所有节点的发布者都被阻塞);消费者很慢时内存告警的持续时间;不同的内存计算策略(allocated);连接 blocked 时已有的 channel 缓冲行为
    京ICP备2026067502号-1京公网安备11010502063487号