跳至主内容

RabbitMQ 性能测量,第一部分

·6 分钟阅读
Simon MacMullen

所以今天我想谈谈 RabbitMQ 性能的某些方面。有大量的变量影响您可以从 RabbitMQ 服务器获得的整体性能水平,今天我们将尝试调整其中的一些变量,看看会发生什么。

本文的目的不是为了说服您 RabbitMQ 是世界上最快的消息队列——它通常不是(尽管我们仍然认为我们做得相当不错)——而是让您了解在不同情况下可以预期的性能。

图中展示的所有图表和统计数据均在配备双 Xeon E5530 和 40GB RAM 的 PowerEdge R610 上测量。主要是因为它是我们当时拥有的最快的机器。一个不太理想的主要因素是,由于我们可用的硬件有限,客户端与服务器运行在同一台机器上。我们使用了 RabbitMQ 2.8.1(在大多数情况下)和启用了 HiPE 编译的 Erlang R15B。

顺便说一下,生成所有这些统计数据的代码可在 rabbitmq-java-client 的 bug24527 分支中找到(尽管目前还相当粗糙)。最终它将被合并到默认分支,并且也会更容易使用。我们希望如此。

RabbitMQ 2.8.0+ 中的流控制

但首先,我需要介绍 RabbitMQ 2.8.0+ 中的一项新功能——内部流控制。RabbitMQ 内部由多个 Erlang 进程组成,它们相互传递消息。每个进程都有一个邮箱,其中包含它已接收但尚未处理的消息。这些邮箱可以增长到无限大小。

这意味着,除非从网络套接字接收数据的第一个进程是链中最慢的(它不是),否则当 RabbitMQ 服务器负载很高时,消息会永远堆积在进程邮箱中。或者更确切地说,直到我们内存耗尽。或者更确切地说,直到内存警报响起。届时,服务器将停止接受新消息,直到它自行恢复。

问题是,这可能需要一些时间。下面的图表(本文中唯一一个针对 RabbitMQ 2.7.1 制作的图表)显示了一个尽可能快地将小消息发布到代理并尽可能快地消费这些消息的简单过程,并关闭了确认、确认、持久化等功能。我们绘制了发送速率、接收速率和延迟(消息发送到接收所花费的时间)随时间的变化。请注意,延迟是按对数刻度显示的。

简单 1 -> 1 自动应答 (2.7.1)

哎哟!这可不太愉快。有几点应该很明显:

  • 发送速率和接收速率波动很大。
  • 发送速率有两分钟降至零(这是内存警报第一次响起)。事实上,内存警报在最后再次响起。
  • 延迟持续增加(看看刻度——我们显示的是微秒,但我们也可以轻松地以分钟为单位测量它)。

(大约 440 秒时的延迟小幅下降是由于 200 秒之前发布的所有消息都已被消耗,之后是长时间的间隔。)

当然,这只是在将服务器推向极限时可能出现的行为。但我们正在进行基准测试——我们希望这样做。而且,服务器在生产环境中也会面临压力。

现在让我们看看针对 RabbitMQ 2.8.1 服务器进行的相同实验。

简单 1 -> 1 自动应答 (2.8.1)

这看起来平静多了!发送速率、接收速率和延迟都接近恒定。原因是内部流控制。延迟约为 400 毫秒(与负载较小的服务器相比仍然很高,原因稍后讨论)。

这些图表没有显示内存消耗,但情况是相同的——在这种情况下,2.7.1 会消耗大量内存并在内存警报阈值附近波动,而 2.8.1 会使用相当恒定、相当低的内存量。

链中的每个进程都会向可以向其发送消息的进程发出信用。进程在发送消息时消耗信用,并在接收消息时发出更多信用。当一个进程用完信用时,它将停止向其上游进程发出更多信用。最终,我们到达读取网络套接字字节的进程。当**该**进程用完信用时,它会停止读取,直到获得更多信用。这与 2.7.1 代理触发内存警报时相同,除了它每秒发生多次而不是需要几分钟,并且我们对内存的使用进行了更多控制。

那么 400 毫秒的延迟从何而来?嗯,管道中的每个阶段仍然有消息排队,因此消息需要一段时间才能从头到尾。这占了部分延迟。然而,大部分延迟来自服务器最前端一个看不见的“邮箱”——

  • 操作系统提供的 TCP 缓冲区。在 Linux 上,操作系统允许高达 8MB 的消息在 TCP 堆栈中积压。当然,8MB 听起来不多,但我们处理的是微小消息(并且每条消息都需要进行路由决策、权限检查等)。

但重要的是要记住,我们倾向于在达到性能极限时看到最差的延迟。所以这是本周最后一张图表——

1 -> 1 尝试发送速率与延迟

请注意,横轴不再是时间。我们现在显示了许多上述运行的结果,每个点代表一次运行。

在上面的图表中,我们正在全速运行,但在这里,我们以不同点限制速率,直到达到我们能实现的最大速率。因此,黄色线显示尝试的速率与实现的速率——可以看到它几乎是纯粹的 1:1 线性(当有可用容量时,如果我们尝试更快地发布,我们将成功),然后当我们达到极限时停止增长。

但看看延迟!在较低的发布速率下,我们的延迟远小于一毫秒。但随着服务器变得更忙,这种延迟会逐渐增加。当我们无法以更快的速度发布时,我们会达到延迟的墙——TCP 缓冲区开始填满,很快消息需要数百毫秒才能通过。

因此,希望我们已经展示了 RabbitMQ 2.8.1 在重载情况下比以前的版本提供了更可靠的性能,并展示了当您的消息队列过载时延迟会飙升。下周请继续收看,了解消息传递的不同使用方式如何影响性能!

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