bigywater.tech
RabbitMQ · 28

消息大小对吞吐的影响

消息越大吞吐越低是常识,但具体是怎么降的?拐点在哪里?大消息在线上被怎么拆帧?有没有大小上限?放在队列里占内存还是占磁盘?这篇用同一套带 confirm 的异步发布把这些都量一遍。

59713 → 1436
10 B 与 1 MiB 消息的发布吞吐(条/秒);1 MiB 时带宽 1435.7 MiB/秒
3 个 ContentBody
300 KiB 的消息按 frame_max 131072 拆成的帧数
16 MiB
max_message_size:17 MiB 的消息得到 406

吞吐曲线

实测 · 本机执行输出
  消息大小      条数      耗时     条/秒     MiB/秒
  10 B         30000      502 ms     59713       0.6
  100 B        30000      511 ms     58765       5.6
  1 KiB        30000      549 ms     54651      53.4
  10 KiB       30000      638 ms     47041     459.4
  100 KiB       3072      221 ms     13876    1355.1
  1 MiB          300      209 ms      1436    1435.7

小消息(≤ 1 KiB)吞吐约 5~6 万条/秒,每条的处理开销主导;从 10 KiB 起条数下降而带宽上升,100 KiB~1 MiB 时带宽约 1.4 GiB/秒。

队列类型

实测 · 本机执行输出
  消息大小      条数      耗时     条/秒     MiB/秒
  10 B         30000      539 ms     55621       0.5
  100 B        30000      515 ms     58295       5.6
  1 KiB        30000      546 ms     54962      53.7
  10 KiB       30000      642 ms     46703     456.1
  100 KiB       3072      219 ms     14035    1370.6

单节点上 classic 和 quorum 的吞吐曲线几乎重合,消息大小才是主要因素。

帧

实测 · 本机执行输出
  协商的 frame_max = 131072
  一条 300 KiB 的消息:Basic.Publish 1 个帧 + ContentHeader 1 个帧 + ContentBody 3 个帧(每个最大 131072 字节,最后一个 45080 字节)

消息体按协商的 frame_max(131072)拆成多个 ContentBody 帧;ContentHeader 记录总长度。

上限

实测 · 本机执行输出
  1 MiB: 成功
  16 MiB: 成功
  17 MiB: ChannelClosedByBroker: (406, 'PRECONDITION_FAILED - message size 17825792 is larger than configured max size 16777216')
  130 MiB: ChannelClosedByBroker: (406, 'PRECONDITION_FAILED - message size 136314880 is larger than configured max size 16777216')
  $ rabbitmqctl eval "application:get_env(rabbit, max_message_size)."  →  {ok,16777216}

max_message_size 默认 16 MiB,超过得到 406 PRECONDITION_FAILED,channel 被关。

内存与磁盘

实测 · 本机执行输出
  放入前:broker RSS 137 MiB,数据目录 0.1 MiB
  1000 条 × 1 MiB 之后:broker RSS 152 MiB,数据目录 1000 MiB;队列 messages=1000 messages_ram=1 队列进程内存=0.0 MiB

大消息放进经典队列后主要在磁盘上(1000 条 1 MiB:磁盘 +1000 MiB,RSS +15 MiB)。

分步演示

消息大小
本步的对象

    本文用到的工具与边界

    • 本机 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,数字每次运行会有小幅抖动。吞吐用 pika SelectConnection 带 confirm 异步发布(在途 1000),持久化,3 轮取中位数,每种大小条数 = min(30000, 300 MiB ÷ 大小);第三节线上帧经自己写的代理;第五节在全新节点上用 ps 读 RSS、du 读数据目录
    • 没有验证:多副本 quorum 队列下大消息的复制代价;消费端的吞吐随消息大小的变化;非持久化消息;调大 max_message_size 后极大消息的行为;frame_max 调整的影响;TLS 下的大消息;Linux / 真实磁盘上的 MiB/秒(这里是 macOS 笔记本 SSD)
    京ICP备2026067502号-1京公网安备11010502063487号