队列长度限制是保护 broker 的第一道防线,但“满了之后丢谁”“限制到底数什么”“quorum 队列也一样吗”都有细节。这篇在 RabbitMQ 4.3.6 上把每种溢出策略和计数口径都量一遍。
队列里剩: ['m5', 'm6', 'm7', 'm8', 'm9']
默认策略:队列满了把队头(最老的)挤出去,留下最新的。没有通知,配了死信交换机时则变成 maxlen 死信(见死信那篇)。
不开 confirm 发 10 条,队列里是: ['m0', 'm1', 'm2', 'm3', 'm4'](最先到的 5 条,后 5 条悄悄丢了) 开 confirm 发 10 条的结果: ['ack', 'ack', 'ack', 'ack', 'ack', 'NACK', 'NACK', 'NACK', 'NACK', 'NACK']
满了拒绝新发布。开了 publisher confirm 的发布方收到 Nack;没开就悄悄丢。
主队列: ['m0', 'm1', 'm2']
死信队列: [('m3', 'maxlen'), ('m4', 'maxlen'), ('m5', 'maxlen')]
对比 drop-head + 死信:主队列 ['m3', 'm4', 'm5'];死信队列(被挤出去的最老的)是 [('m0', 'maxlen'), ('m1', 'maxlen'), ('m2', 'maxlen')]在拒绝新发布的同时把被拒绝的消息送进死信交换机,reason=maxlen。
留下 10 条(100 字节/条,限制 1000 字节) 同样的消息体再加上约 100 字节的头/属性:留下 10 条——限制只数消息体,不数属性 单条 2000 字节(比限制大)发 3 条:留下 0 条
x-max-length-bytes 只数消息体,不数头和属性;比上限还大的单条消息留不下来。
max-length=10 且 max-bytes=500,发 20 条 100 字节:留下 5 条(字节限制先到)
队列参数 x-max-length=10 + policy max-length=4,发 20 条:留下 4 条;policy 查询: ['/', 'lim', '^l6$', 'queues', '{"max-length":4}']队列参数和 policy 同时给了长度限制,取较小的;和字节限制一起设,先到的生效。policy 的好处是可以不重建队列就改。
取走 3 条不 ack 后: (ready, unacked) = (0, 3) 再发 10 条后: (ready, unacked) = (3, 3)(上限只管 ready 的)
已经投递出去等确认的消息不计入长度,所以 ready + unacked 可以超过上限。
quorum + drop-head(连发 10 条,上限 5):留下 ['m5', 'm6', 'm7', 'm8', 'm9'] quorum + reject-publish,不开 confirm 连发 10 条(上限 5):留下 10 条 quorum + reject-publish,开 confirm 每条间隔 10 ms 发 30 条的结果: AAAAAANNNNNNNNNNNNNNNNNNNNNNNN(A = Ack,N = Nack);队列里最后 6 条
drop-head 与经典队列一致;reject-publish 不精确:快速连发会超限,逐条 confirm 时也多收一条才开始 Nack。