RabbitMQ-队列
一、基础
队列是具有两个主要操作的顺序数据结构:项目可以在尾部入队(添加)和从头部出队(消耗)。队列在消息传递技术领域发挥着重要作用:许多消息传递协议和工具假定发布者和消费者 使用类似队列的存储机制进行通信。
RabbitMQ 中的队列是FIFO(“先进先出”)。一些队列特性,即消费者的优先级和重新排队,会影响消费者观察到的排序。
二、队列名称
队列具有名称,以便应用程序可以引用它们。
应用程序可以选择队列名称或要求Broker为它们生成名称 。队列名称最多可以是 255 个字节的 UTF-8 字符。
以“amq”开头的队列名称。保留Broker内部使用。尝试使用违反此规则的名称声明队列将导致通道级异常 ,回复代码为 403 ( ACCESS_REFUSED )。
三、服务器命名的队列
在 AMQP 0-9-1 中,Broker可以代表应用程序生成唯一的队列名称。要使用此功能,请传递一个空字符串作为队列名称参数:同一通道中的后续方法可以使用预期队列名称的空字符串来获取相同的生成名称。这是有效的,因为通道会记住最后一个服务器生成的队列名称。
服务器命名的队列旨在用于本质上是瞬态的并且特定于特定消费者(应用程序实例)的状态。应用程序可以在消息元数据中共享这些名称,以让其他应用程序响应它们。否则,服务器命名队列的名称应该只由声明的应用程序实例知道和使用。实例还应该为队列设置适当的绑定(路由),以便发布者可以使用众所周知的交换而不是直接使用服务器生成的队列名称。
四、特性
队列具有定义其行为方式的属性。有一组强制属性和可选属性的映射:
- 名称
- 持久(队列将在Broker重新启动后继续存在)
- 独占(仅由一个连接使用,当该连接关闭时队列将被删除)
- 自动删除(当最后一个消费者退订时删除至少有一个消费者的队列)
- 参数(可选;由插件和特定于Broker的功能使用,例如消息 TTL、队列长度限制等)
请注意,并非所有属性组合在实践中都有意义。例如,自动删除和独占队列应该是server-named。此类队列应该用于特定于客户端或特定于连接(会话)的数据。
当自动删除或独占队列使用众所周知的(静态)名称时,在客户端断开连接和立即重新连接的情况下,RabbitMQ 节点之间将出现自然的竞争条件,这将删除此类队列并恢复客户端将尝试重新声明它们. 这可能导致客户端连接恢复失败或异常,并造成不必要的混乱或影响应用程序的可用性。
五、声明和属性等价
在使用队列之前,必须先声明它。如果队列不存在,则声明队列将导致它被创建。如果队列已经存在并且其属性与声明中的相同,则声明将无效。当现有队列属性与声明中的不同时,将引发代码为 406 ( PRECONDITION_FAILED )的通道级异常。
六、消息排序
RabbitMQ 中的队列是消息的有序集合。消息以先进先出的方式入队和出队(交付给消费者)。
不保证优先级和分片队列的 FIFO 排序。
排序也可能受到多个竞争消费者的存在、 消费者优先级、消息重新传递的影响。这适用于任何类型的重新交付:渠道关闭和 负面消费者确认后的自动交付。
应用程序可以假设在单个通道上发布的消息将按发布顺序排列在它们路由到的所有队列中。当发布发生在多个连接或通道上时,它们的消息序列将同时路由并交错。
消费应用程序可以假设向单个消费者的初始交付(重新交付属性设置为false的那些)按照与它们入队时相同的 FIFO 顺序执行。对于重复交付(redelivered属性设置为true),原始排序可能会受到消费者确认和重新交付时间的影响,因此无法保证。
在有多个消费者的情况下,消息将按 FIFO 顺序出队以进行传递,但实际传递将发生在多个消费者身上。如果所有消费者具有相同的优先级,则将在循环的基础上进行挑选。只有未超过其预取值 (未确认的未确认交付的数量)的通道上的消费者才会被考虑。
七、耐用性
队列可以是持久的或暂时的。持久队列的元数据存储在磁盘上,而临时队列的元数据尽可能存储在内存中。 在某些协议(例如 AMQP 0-9-1 和 MQTT)中,发布时的消息也有同样的区别。
在持久性很重要的环境和用例中,应用程序必须使用持久队列并确保发布将已发布消息标记为持久。
临时队列将在节点启动时被删除。因此,按照设计,它们将无法在节点重启后幸存下来。临时队列中的消息也将被丢弃。
持久队列将在节点启动时恢复,包括其中发布为持久的消息。作为瞬态发布的消息将在恢复期间被丢弃,即使它们存储在持久队列中。