跳到主要内容

同步的终结:3.3 版本中的性能改进

·4 分钟阅读
Simon MacMullen

昨天我们发布了坏消息,所以今天我们来谈谈(一些)好消息:某些类型的发布和消费现在速度更快了,尤其是在集群中。

RabbitMQ 的各种内部组件通过在它们之间传递消息来进行通信(在节点内部和跨集群之间);这就是 Erlang 应用程序的工作方式。RabbitMQ 的一个设计目标一直是,AMQP 中的异步操作(即发送和接收消息以及确认)在服务器内部也应该是异步的。这样做有一个很好的理由:每当您执行同步操作时,您都会受到延迟的限制,因为您需要等待回复,因此异步是实现更快消息传递的途径。

不幸的是,虽然这始终是一个目标,但我们并非总是能实现它。特别是,在 AMQP 中的异步消息传递在服务器内部变成同步的两个地方仍然存在:强制发布,以及使用通过 basic.qos 设置的预取限制来消费消息。这些遗留问题已在 3.3.0 版本中得到修复。

作为回顾,强制发布意味着如果消息最终没有路由到任何队列,则告知发布者,而使用预取限制进行消费意味着确保您只向消费者发送最大数量的未确认消息

那么让我们来看一些数字...

强制发布

3.2.43.3.0
强制发布5.0kHz 平衡12.9kHz 平衡

此测试涉及单台机器上的双节点集群,发布者连接到一个节点,消费者连接到另一个节点,队列与消费者位于同一节点上。消息很小且非持久化,并且未使用确认或发布确认。机器是 Dell Precision 工作站,但重点是查看此处的相对性能变化。

希望您能看到同步对性能的损害有多大。请记住,同步消息传递带来的性能损失与网络延迟成正比 - 而这两个节点位于同一台机器上,因此真正的集群的性能下降会更严重。

另请注意,在这两种情况下,发送和接收速率都是相同的;消息没有在队列中积压。

使用预取限制进行消费

我们预计高预取限制会提供与无预取限制几乎相同的性能,并且随着我们降低限制,我们将获得更低的性能,因为在某些时候,队列将必须等待消费者确认消息才能发送另一条消息。

3.2.43.3.0
无限制15.0kHz 发送 / 11.0kHz 接收15.8kHz 平衡
prefetch_limit=10006.2kHz 发送 / 3.6kHz 接收15.8kHz 平衡
prefetch_limit=1006.2kHz 发送 / 3.6kHz 接收13.5kHz 平衡
prefetch_limit=106.2kHz 发送 / 3.6kHz 接收14.0kHz 发送 / 7.0kHz 接收
prefetch_limit=118.0kHz 发送 / 0.9kHz 接收18.0kHz 发送 / 0.9kHz 接收

此测试具有与上述相同的特性,不同之处在于队列与发布者位于同一节点上,并且在消费时使用了确认。

此表中的数字显示了几个有趣的效应

  • 即使关闭预取限制,3.3.0 也稍微快一些,并防止了消息积压。这是由于一个新功能,我将在以后的博客文章中讨论。
  • 足够高的预取限制(使得队列永远不必等待消费者)在 3.3.0 中没有性能成本,而任何预取限制都会损害 3.2.4 中的性能。
  • 3.2.4 中介于 10、100 和 1000 之间的所有预取限制都具有完全相同(糟糕)的性能 - 这是因为限制因素最终证明是消费通道和队列之间的同步通信。
  • 最后,当我们达到预取限制为 1 时,3.2.4 和 3.3.0 的性能都同样糟糕 - 这是因为限制因素现在已变为我们等待消费者一次确认一条消息的时间量。

因此,通过这些更改,RabbitMQ 的消息传递内部机制在所有情况下都变为异步,从而带来了巨大的性能优势。值得指出的是,basic.qos 的语义必须略作更改才能实现这一点,但这对于如此大的改进来说似乎是一个很小的代价。

© . All rights reserved.