在 RabbitMQ 4.3.6 上用 TCP 代理解析 AMQP 0-9-1 的帧:连接握手 7 个帧,发布一条消息是方法帧加内容头加内容体 3 个帧;channel 级错误只关 channel,连接级错误关整条连接;rabbitmqctl 列出预置的 exchange、队列和绑定;100 个连接约 +1100 个 Erlang 进程,而 1 个连接 100 个 channel 只 +407。
在 RabbitMQ 4.3.6 上实测四种 exchange 的路由规则:direct 逐字节相等、fanout 忽略 key、topic 的 * 与 # 匹配(含零个单词)、headers 的 x-match all/any;同队列多个绑定只收一份;1000 个绑定时 direct、topic 约 276~295 ms,headers 3387 ms。
在 RabbitMQ 4.3.6 上看默认 exchange:空串名字、每个队列自动绑上 key=队列名的绑定;写错队列名消息被丢弃,mandatory + confirm 才有 UnroutableError;它不能被删、绑、重新声明(403);队列名上限 255 字节;20000 条消息走默认 exchange(中位数 545 ms)与显式 direct(536 ms)没有可测的差别。
在 RabbitMQ 4.3.6 上实测消息确认:ack 前消息是 unacked 不是消失;nack requeue=True 的消息回到队首且 redelivered 变 True;nack multiple=True 一次丢一批;delivery tag 是每个 channel 自己的,跨 channel 确认得 406;auto_ack 的消息随消费者丢失;requeue 的毒消息 1 秒被投递 11967 次。
在 RabbitMQ 4.3.6 上用 TCP 代理看发布确认:同步发布一条一个 Ack;异步发 5000 条 broker 合并成 619 个 Ack(603 个 multiple=True);每条同步等 5752 条/秒、在途上限 100 时 54057 条/秒;不可路由的消息也会被 Ack,mandatory 会先收到 Basic.Return;reject-publish 满队列时收到 Basic.Nack。
在 RabbitMQ 4.3.6 上实测 mandatory:路由不到的消息会以 312 NO_ROUTE 连同属性和消息体原样退回,Return 是异步的;direct、fanout、topic、headers 的不匹配都算不可路由,exchange 不存在则是 channel 错误;备用交换机能接住时不触发 Return;可路由时 mandatory 开销不可测。
在 RabbitMQ 4.3.6 上实测持久化:默认拒绝非持久非排他队列(541);队列 durable 与消息 persistent 要同时满足重启后才保留;kill -9 时没等 confirm 的 5000 条只剩 4080 条,等了 confirm 的 5000 条全在;persistent 与 transient 消息写盘量几乎一样;非持久 exchange 在 4.3.6 里重启后仍在。
在 RabbitMQ 4.3.6 上实测 prefetch:它限制的是已投递未确认的条数;global_qos 在 4.3.6 默认被当成每消费者限制;自动确认不受限;loopback 上 prefetch=1 是 9718 条/秒、10 是 29665 条/秒;往返 10 ms 时 prefetch=1 只有 78 条/秒、1000 是 13488 条/秒;prefetch=1000 的消费者崩溃会让 1000 条重投。
在 RabbitMQ 4.3.6 上实测消息分发:相同速度的消费者轮流拿;一快一慢时 prefetch=0 要 9.37 s 而 prefetch=1 只要 1.83 s;卡住的消费者扣住的消息数等于 prefetch;x-priority 让高优先级的消费者先拿,满了才溢出;相同消费者 1/2/4/8 个耗时按 1/N 缩短。
在 RabbitMQ 4.3.6 上实测死信:reject / TTL 过期 / 队列超长三种原因的 x-death 头(count、reason、queue、exchange、routing-keys)和 x-first/last-death;x-dead-letter-routing-key 的影响;DLX 配错消息静默消失;用 wait 队列 + TTL 实现重试并用 count 计数;全是 expired 的死信环会被检测并丢弃。
在 RabbitMQ 4.3.6 上实测 TTL + 死信做延迟消息:队列级 TTL 1000 ms 的延迟误差约 2 ms;单条消息 expiration 不同时,短的被队头的长的挡住(300 ms 的拖到 3004 ms),classic 和 quorum 都一样;一种延迟一个队列可避开阻塞;TTL 500 ms 的延迟 501~506 ms;50000 条 1 KB 延迟消息占 48.8 MiB。
在 RabbitMQ 4.3.6 上实测优先级队列:按优先级从大到小取出,同级先进先出;超出上限按上限算,没声明的队列忽略优先级;已预取的消息插不了队(prefetch=20 时 HIGH 排第 21);255 档比不设慢到 3.9 倍、空队列占 1.1 MB;quorum 队列按完整优先级排序但不接受 x-max-priority。