说明
在上篇博文《RabbitMQ学习(十三):死信交换机》中,我对官方文档有关死信交换机的内容进行了翻译和学习,文中提到消息成为死信的原因有三种,队列长度的限制就是其中之一。本篇博文我将继续翻译学习官方文档中有关队列长度限制的相关的内容,通过本文记录学习总结有关队列长度限制如何设置,超出限制队列如何处理等内容。
正文
概述
队列的最大长度限制可以是限制消息的数量,或者是消息的总字节数(总字节数表示的是所有的消息体的字节数,忽略消息的属性和任何头部信息),又或者两者都进行了限制。
对于任意一个队列,队列的最大长度可以通过客户端在队列声明时使用队列的可选参数进行配置,也可以在服务器通过policy命令设置。如果同时使用这两种方式设置了队列的最大长度,那么其中较小的值将被使用。
队列长度也可以通过operator policies进行设置。
在所有情况中,只有处于ready状态的消息被计数,未被确认的消息不会被计数受到limit的限制。
来自rabbitmqctl list_queues命令或者管理API的两个字段值message_ready和message_bytes_ready显示了消息的限制数量值。
队列溢出的默认行为
当队列的消息超过设置的最大长度或大小时,RabbitMQ默认的做法是将处于队列头部的信息(队列中最老的消息)丢弃或变成死信。可以通过设置overflow的值来改变这种方式。
队列的溢出行为
使用overflow参数来配置队列的溢出操作。如果overflow值设置为reject-publish,那么最近被发送的消息将被丢弃。另外,如果开启了发送者确认模式,那么会使用basic.nack方法通知发送者消息被拒绝。如果消息被同时路由到多个队列,并且被其中最少一个队列拒绝,那么通道将会使用basic.nack方法来通知消费者消息被拒绝,但是消息仍可以继续发送给可以接受它的队列。
使用policy定义队列的最大长度
使用policy命令来设置队列的最大长度,通过设置max-length或max-length-bytes的值进行配置:
rabbitmqctl set_policy my-pol "^one-meg$" '{"max-length-bytes":1048576}' --apply-to queues
以上代码设置了my-pol的策略,该策略保证了one-meg队列最多只能有1MiB的数据。当达到这个限制时,将从队列的头部丢弃最老的消息。
定义溢出操作—无论是从队列头部丢弃消息还是拒绝新的消息,都可以通过在policy命令中添加overflow来定义。如:
rabbitmqctl set_policy my-pol "^two-messages$" '{"max-length":2,"overflow":"reject-publish"}' --apply-to queues
以上代码中,my-pol策略保证了two-messages队列最多只能包含两个消息,并且只要队列中消息数已经达到限制并且发送者确认开启,就会发送basic.nack响应通知发送者拒绝消息。
也可以通过管理插件来定义policies,更多内容详见policy documentation
使用x-arguments定义队列的最大长度
队列的最大消息数可以在声明队列时设置参数x-max-length的值来配置,该值必须是要给非负整数。
队列的消息最大字节数可以在声明队列时设置参数x-max-length-bytes的值来配置,该值必须是一个非负整数。
如果同时设置了这两个参数值,那么最先到达限制时就会被使用。
队列的溢出操作可以在队列声明时设置参数x-overflow的值,该值是一个字符串。它的值可以是drop-head(默认值)或者reject-publish。
以下是使用java代码声明配置队列最大长度为10个消息:
Map<String, Object> args = new HashMap<>();
args.put("x-max-length", 10);
channel.queueDeclare("myqueue", false, false, false, args);