队列 Queues
尽可能少排队
队列中的许多消息会对 RAM 的使用造成很大的负担。为了释放 RAM,RabbitMQ 将(页面输出)消息刷新到磁盘。此过程会降低排队速度。当有许多消息需要分页取出时,分页过程通常会花费时间并阻止队列处理消息。许多消息可能会对中间件的性能产生负面影响。 当有许多消息重启集群时,也是费时的,因为必须重建索引。重新启动后,在群集中的节点之间同步消息也需要时间。
启用延迟队列以获得可预测的性能
在 RabbitMQ 3.6 中添加了一个名为 lazy queues 的功能。懒惰队列是消息自动存储到磁盘上的队列。只有在需要时才将消息加载到内存中。对于懒惰的队列,消息直接进入磁盘,因此 RAM 的使用被最小化,但是吞吐时间将花费更长的时间。
懒惰的队列以更好的可预测性的方式,创建了一个更稳定的集群。要让您的消息不出现警告,请刷新到磁盘。您不会突然被一个性能冲击问题所困扰。如果您一次发送大量消息(例如处理批处理作业),或者如果您认为您的消费者一直无法跟上发布者的速度,建议您启用延迟队列。
注意
如果需要非常高的性能,且队列时间总是很短,您应该禁用延迟队列,或者设置最大长度策略。
限制队列大小(TTL 或最大长度)
对于经常受到消息峰值冲击的应用程序,以及要求吞吐量比其他任何程序都重要的应用程序,可以推荐的另一做法是设置队列的最大长度。这样可以通过丢弃来自队列头部的消息来保持队列的简短性,从而使队列永远不会超过 max-length 设置。
队列数量
队列在 RabbitMQ 中是单线程的,一个队列可以处理大约 50k 条消息/秒。如果您有多个队列和消费者,您可以在多核系统上获得更好的吞吐量。如果在底层节点上拥有与核心一样多的队列,那么您将获得最佳吞吐量。 RabbitMQ 管理接口为集群中的每个队列收集和计算度量。如果您有数千个活动队列和使用者,这可能会减慢服务器的运行速度。如果队列太多,CPU 和 RAM 的使用也可能受到负面影响。
将队列拆分到不同的核心上
队列性能受限于一个 CPU 核心。因此,如果将队列拆分到不同的核心,您将获得更好的性能。如果您拥有 RabbitMQ 集群,您也可以将他们拆分到不同的节点。 RabbitMQ 队列绑定到最初声明它们的节点。即使您创建了一个 RabbitMQ 中间件集群,所有路由到特定队列的消息都将转到该队列所在的节点。您可以在节点之间平均地手动拆分队列,但缺点是您需要记住队列的位置。 如果您有多个节点或具有多个核心的单节点集群,您可以使用如下两个插件:
-
Consistent hash exchange plugin
一致的哈希交换插件允许您使用 exchange 在队列之间加载平衡消息。通过消息的路由密钥,发送到 exchange 的消息在多个队列中均匀一致地分布。该插件创建路由密钥的散列,并在绑定到该 exchange 的队列之间传播消息。如果不向发布服务器中添加充足的有关队列数量及其 bindings 的信息,手动执行此操作可能很快就会出现问题。 如果需要最大限度地使用集群中的多个核心,可以使用一致的哈希交换插件。注意
从所有队列中消耗是很重要的。
-
RabbitMQ sharding
RabbitMQ sharding 插件将自动对队列进行分区,一旦您将一个 exchange 定义为 sharded,那么在每个集群节点上自动创建支持队列,并在它们之间共享消息。RabbitMQ sharding 向使用者显示了一个队列,但它可能是后台运行在它后面的多个队列。RabbitMQ sharding 插件为您提供了一个集中的位置,通过向集群中的其他节点添加队列,您可以将消息以及跨多个节点的负载平衡发送到该位置。
不要在临时队列上设置自己的名称
当您想要在生产者和消费者之间共享队列时,为队列命名是很重要的,但是如果您使用临时队列,则不重要。相反,您应该让服务器使用一个随机的队列名称,而不是自己命名一个,或者修改 RabbitMQ 策略。
自动删除不再使用的队列
客户机连接可能会失败,并可能留下未使用的资源(队列),留下许多队列可能会影响性能。
自动删除队列有三种方法:
- 您可以在队列上设置TTL策略。例如,28 天的 TTL 策略将删除 28 天内未使用的队列。
- 当自动删除队列的最后一个使用者已取消或通道/连接已关闭时(或当它与服务器失去 TCP 连接时),自动删除队列将被删除。
- 专用队列只能通过声明连接被使用(从哪里使用、清除、删除等)。专用队列在其声明连接关闭或消失时被删除(例如,由于底层 TCP 连接丢失)。
为优先级队列设置使用限制
在 Erlang VM 的内部队列每个队列均使用了一个优先级别,他们耗费了一些资源。在大多数情况下,不超过 5 个优先级就足够了。