跳至主内容

RabbitMQ 4.1 性能改进

·6 分钟阅读

RabbitMQ 4.1 即将发布(更新:已发布),并且一如既往,除了新功能之外,我们还进行了一些内部改进,以提供更好的性能。

至少有 4 项值得注意的改进

  1. 仲裁队列的内存使用率更低且更稳定
  2. 消费长仲裁队列时性能大幅提升
  3. WebSocket 连接性能更佳
  4. TCP 连接内存使用率更低和/或吞吐量更高

仲裁队列 (Quorum Queues):降低内存占用

在许多情况下,RabbitMQ 4.1 中的仲裁队列内存占用更低。您可能已经注意到,过去仲裁队列的内存使用模式呈现锯齿状。它们会填满一个用于近期 Raft 操作的内存缓冲区(缓存),一旦填满,缓冲区会被清空,然后再重新填充。

在 RabbitMQ 4.1 中,这些条目的删除频率大大提高,从而在多种条件下实现了更稳定的内存占用。以下是一个集群在运行 4.0 版本并随后升级到 4.1 版本后的内存使用情况:

Memory usage of a cluster before/after upgrading from 4.0 to 4.1
集群从 4.0 升级到 4.1 前后的内存使用情况

工作负载的具体细节并非至关重要,因为这种差异在许多不同的工作负载下都是可见的,但为了完整起见,详细情况如下:

  • 共有 10 个仲裁队列
  • 所有消息大小均为 1kb
  • 每个队列从单个发布者处接收每秒 500 条消息(即所有队列总计每秒 5000 条消息)
  • 每个队列有一个消费者(绝大多数消息在发布后 10 毫秒内被消费)
  • 由于所有消息都能及时被消费,队列实际上处于空闲状态

值得注意的是,在所有条件下都不能期望出现如此低且稳定的内存占用。例如,仲裁队列会在内存中保留队列中消息的元数据,因此如果您在队列中有大量堆积的消息(消息未被立即消费),这些元数据将占用内存。还有其他因素和内存结构会根据工作负载而增长。尽管如此,在许多常见情况下,内存占用应该会更低且波动更小。

仲裁队列:分担磁盘读取负载

让我们考虑一个完全不同的工作负载——消息在队列中堆积,然后消费者需要追赶进度以清空队列。从历史上看,仲裁队列可能会被大量的消费者涌入所压垮,特别是如果消息很大且消费者请求大量消息(无论是拥有巨大的预取缓冲区,还是存在大量消费者,或者两者兼有)。在这种场景下,队列可能忙于从磁盘读取旧消息(以便分发给消费者),导致发布者不得不等待很长时间才能让队列接收其消息。

在 RabbitMQ 4.1 中,此类磁盘读取被分担到了 AMQP 0.9.1 通道或 AMQP 1.0 会话进程中(取决于所使用的协议)。队列的工作压力显著降低,并能够继续为发布者提供服务。

让我们看看 4.0 和 4.1 之间发布和消费速率的差异

Influx of consumers, 4.0 to 4.1
消费者涌入,4.0 与 4.1 对比

此图表反映的情况如下:

  1. 我们运行了两个集群,4.0 版本(绿线)和 4.1 版本(黄线)
  2. 两个集群均接收每秒约 6000 条消息,每条消息 20kb
  3. 初始状态下没有消费者;因此,消费速率为零
  4. 一段时间后,消费者启动并尝试消费消息
  5. 在每个环境中,现在有 10 个消费者,每个消费者拥有 300 条消息的预取缓冲区
  6. 4.0 环境不堪重负——发布速率下降到仅每秒约 100 条消息
  7. 与此同时,4.1 环境继续为发布者提供服务,没有任何明显影响
  8. 此外,4.1 环境中的消费速率几乎翻了一番
  9. 一旦积压的消息被消费完毕,两个环境都能处理每秒约 7000 条消息的吞吐量

不仅发布者没有被限流,消费者也能够以快得多的速度消费消息!

WebSocket 连接性能提升

为了提供 HTTP 连接,RabbitMQ 使用了一个流行的 Erlang HTTP 服务器 Cowboy(由 Loïc Hoguin 在加入 RabbitMQ 团队前很久开发)。RabbitMQ 4.1 将 Cowboy 升级到 2.13.0 版本,该版本显著提升了 WebSocket 性能,受益者包括所有依赖 Cowboy 的系统,当然也包括 RabbitMQ。因此,对于任何使用基于 WebSocket 的 AMQPMQTTSTOMP 的用户来说,升级到 RabbitMQ 4.1 将特别有益。

TCP 缓冲区自动调优

Cowboy 2.13.0 发布博客中描述的一项关键改进是动态 TCP 缓冲区自动调优。对于 WebSocket 连接,这些 Cowboy 的改进会自动让 RabbitMQ 用户受益,因为 Cowboy 负责处理 RabbitMQ 的 HTTP 连接。

在 RabbitMQ 4.1 中,我们将相同的 TCP 缓冲区自动调优机制集成到了 AMQP 监听器中,这是一个完全独立的代码路径,不使用 Cowboy(因为 Cowboy 是 HTTP 服务器)。得益于此项工作,RabbitMQ 在 AMQP 0.9.1 和 1.0 连接上应能使用更少的内存,且不会产生明显的性能损失。节省的内存量取决于您当前的缓冲区大小和连接数量,但在我们的测试中,在一个拥有数千个连接的系统中,它节省了几百 MB 的内存。

值得指出的是,本段中讨论的缓冲区是用户空间缓冲区,不应与作为内核缓冲区的 recbuf / sndbuf 混淆。后者可以进行静态配置,如果不配置,它们会由 Linux 内核自动调优(其他操作系统上的行为可能有所不同)。

tcp_listen_options.buffer 的值(过去用于控制现已自动调优的缓冲区大小)将被忽略。

© . This site is unofficial and not affiliated with VMware.