跳到主要内容

集群大小调整和其他注意事项

·17 分钟阅读
Jack Vanlightly

这是关于 RabbitMQ 集群大小调整的简短系列文章的开篇。实际的大小调整完全取决于您的硬件和工作负载,因此我们不会告诉您应该配置多少 CPU 和多少 RAM,而是创建一些通用指南,并通过案例研究来说明您应该考虑哪些事项。

常见问题

对于您的 RabbitMQ 集群,虚拟机大小和虚拟机数量的最佳组合是什么?您应该向上扩展并使用三个具有 32 个 CPU 线程的节点吗?还是应该向外扩展并使用 9 个具有 8 个 CPU 线程的节点?哪种类型的磁盘性价比最高?您需要多少内存?哪种硬件配置更适合吞吐量、延迟和拥有成本?

首先,没有一个统一的答案。如果您在云端运行,那么选择较少,但如果您在本地运行,那么市面上的虚拟化、存储和网络产品及配置数量之多,使得这个问题变得不可能回答。

虽然没有包含具体数字的单一大小调整指南,但我们可以进行大小调整分析,希望这对您自己的大小调整有所帮助。

一些常见注意事项

队列和客户端的数量

客户端连接和队列需要计算时间和内存。如果您有数千个队列和客户端,那么这将影响您的大小调整。您拥有的越多,您可能需要的 CPU 核心和内存就越多。拥有少量队列和客户端对于 RabbitMQ 处理来说更有效——CPU 上下文切换更少,内存开销更少。因此,如果您的工作负载有数千个队列和客户端,那么与您只拥有少量队列和客户端相比,您将需要更大的虚拟机或更多虚拟机才能获得相同的总吞吐量。

各种类型的变更可能会影响集群

  • 连接变更(连接的打开和关闭)
  • 队列和队列绑定变更(队列和绑定的创建和删除)

什么是高吞吐量?

一百万条消息一天听起来可能很多,但是当您将其计算为每秒速率时,它仅降至每秒不到 12 条消息。当您的吞吐量低于每秒 100 条时,您很可能可以将虚拟机的大小调整得非常小。除非您有数千个队列和客户端,否则不太可能看到资源瓶颈。如果您使用集群,在这种速率下,它将纯粹是为了冗余而不是性能。

一旦您超过每秒 1000 条消息(每天 8600 万条或每月 25 亿条),那时您就需要花更多时间进行大小调整分析。对于每秒 1000 条消息,您仍然可以调整得非常小,但可能会出现一些资源瓶颈。

超过 10000 条(每天 8.6 亿条或每月 250 亿条),我建议您更彻底地进行大小调整分析。我们说“快乐的 Rabbit 是空的 Rabbit”。当队列为空时,RabbitMQ 提供最佳吞吐量和最低延迟。消息从内存中提供,通常根本不写入磁盘。当您有大量积压时,消息很可能被读/写到磁盘,数据结构更大且效率更低,并且集群可以处理的最大吞吐量不可避免地会下降。当您拥有高吞吐量集群时,积压可能会从零迅速增加到数百万,因此您需要确保为此进行大小调整。不要只为快乐的情况调整大小,还要为不快乐的情况调整大小。我们稍后将更详细地研究这一点。

哪些工作负载需要更多内存?

经典队列和经典镜像队列会将消息保存在内存中,但在内存不足时开始驱逐它们。这很难预测,因为这是一种动态行为。一个好的做法是,如果您有非常大的队列,则使用惰性队列,因为惰性队列很早就从内存中驱逐消息,并且通常使用的内存要少得多。

Quorum 队列默认情况下始终将所有消息存储在内存中,即使在内存不足的情况下也是如此。这意味着,除非您更改默认设置,否则当队列变长时,您更有可能遇到内存警报(这会阻止所有发布者)。好消息是,这可以使用一些队列属性(例如 x-max-in-memory-length)进行配置,这些属性一次只会将配置数量的消息保存在内存中。这可能应该在您的所有 quorum 队列上设置。这确实意味着更多消息是从磁盘读取的,所以这不是免费的。

冗余如何影响大小调整?

如果您使用 quorum 队列或镜像队列,则每条消息都将传递给多个代理。如果您有一个包含三个代理的集群和复制因子为 3 的 quorum 队列,那么每个代理都将接收每条消息。在这种情况下,我们创建集群只是为了冗余。但我们也可以创建更大的集群以实现可扩展性。我们可以拥有一个包含 9 个代理的集群,以及复制因子为 3 的 quorum 队列,现在我们已经分散了负载,并且可以处理更大的总吞吐量。

增加更多冗余会降低总吞吐量,因此为了抵消这一点,您可以向集群添加更多代理以分散负载。

消息大小如何影响大小调整?

小消息,比如小于 1kb 的消息,不太可能使网络或磁盘饱和。如果您遇到资源瓶颈,那很可能是 CPU。但是,使用较大的消息大小,我们可以轻松地使网络和磁盘饱和。如果您有 1Mb 的消息和 5gbit 的网络,那么使用经典队列,您将以每秒 300 多条消息的速度使网络饱和。如果您使用 quorum 队列或镜像队列,则速度会更低,因为消息不仅必须发送/接收到客户端,还必须在代理之间复制。

您计划使用 Federation 吗?

Federation 涉及在 RabbitMQ 代理上运行 AMQP 客户端。这意味着它们与通道和队列争夺相同的资源。这可能意味着您需要增加虚拟机的大小/数量。还要考虑到

  • 如果您对本地队列(充当发件箱)使用镜像队列,那么您将在集群中复制这些传出的消息。冗余是昂贵的。
  • 消息将通过网络传输到另一个代理,这会增加您的网络大小调整。

始终在您的大小调整测试中包含 federation 设置。

大小调整 - AWS 案例研究

我们现在将通过一个案例研究,其中将涉及识别工作负载、定义我们对端到端延迟和弹性的要求,最后是一系列测试,这些测试将根据这些要求衡量不同的虚拟机大小和数量。

请记住,这是一个案例研究,因此您自己的要求和工作负载可能与此非常不同。这也是一个详细的分析,适用于 RabbitMQ 是您基础设施的关键部分,并且值得投入时间进行彻底的大小调整分析的情况。

案例研究工作负载

为了我们的案例研究的目的,我选择了一个中等大小、高强度的工作负载。这意味着我们有适量的队列和客户端,但通过它们推送大量消息。

  • 200 个发布者
  • 100 个队列
  • 200 个消费者
  • 没有扇出 - 使用默认交换机进行点对点
  • 1kb 消息大小
  • 每条消息 10 毫秒处理时间
  • Java 客户端
  • 恒定速率

我们在大多数时候的吞吐量相对稳定在 5000 msg/s,但高峰期高达 20,000 msg/s,每天可能持续一到两个小时。我们预计未来一年流量可能会增加 10%。

我们的要求

我们希望根据峰值吞吐量加上额外的 10,000 msg/s 来调整集群大小,以防出现意外的高流量,这也将涵盖预期的 10% 的增长。我们不需要根据超出此范围的预期增长来调整大小,因为我们将来可以轻松升级 EC2 实例。

我们想使用复制队列,因为这些消息对业务具有货币价值。因此,我们将对镜像队列和较新的 quorum 队列进行大小调整分析。

在延迟方面,只要我们低于 1 秒的第 99 百分位端到端延迟(消息发布和消费之间的时间),我们就很高兴。

最后,我们希望确保即使在不利条件下(例如丢失代理或下游中断影响消费者吞吐量),我们也能达到吞吐量峰值。如果队列积压因消费者运行缓慢而增长,我们希望吸收消息入口(保持发布速率)。减慢发布速度对我们来说是有金钱成本的。

测试

理想条件 - 强度递增测试

对于发布速率,我们实际上将运行一系列基准测试,这些测试具有不同的发布速率,涵盖 5k 到 30k msg/s 及以上。目的是确定在什么速率下,选择的大小调整可以提供必要的结果,以及何时开始遇到困难并且不满足要求。这是快乐的场景,RabbitMQ 很可能保持为空(并且速度最快),因为消费者始终保持同步(直到集群达到其容量)。

我们将使用以下速率(所有发布者的总计)

  • 1000 msg/s(每小时 = 360 万,每天 = 8640 万,每月 = 25 亿)
  • 5000 msg/s(每小时 = 1800 万,每天 = 4.32 亿,每月 = 129 亿)
  • 10000 msg/s(每小时 = 3600 万,每天 = 8.64 亿,每月 = 258 亿)
  • 15000 msg/s(每小时 = 5400 万,每天 = 13 亿,每月 = 389 亿)
  • ...
  • 70000 msg/s(每小时 = 2.52 亿,每天 = 60 亿,每月 = 1814 亿)

不利条件 - 丢失代理测试

我们将测试即使在代理关闭的情况下,所选的集群大小是否可以处理峰值速率 (30k msg/s)。代理可能会因多种原因而关闭:我们重新启动机器作为操作系统补丁安装的一部分、磁盘故障、网络分区等。最坏的情况是这发生在峰值负载期间。

不利条件 - 消费速率下降,创建积压测试

数据库服务器过载,或者下游系统中的网络速度减慢,或者第三方 API 运行缓慢。无论哪种方式,处理每条消息的时间都从 10 毫秒增加到 30 毫秒,从而降低了消费速率。我们能否继续接受不受影响的发布速率并吸收积压?

不利条件 - 发布速率达到非常高的峰值,超过消费者容量测试

营销活动突然爆火,我们获得的流量远超预期,以至于我们的处理系统无法处理负载。我们能否将流量作为可以稍后处理的大型队列积压来吸收?

集群

集群大小和存储卷

我们在 AWS ec2 上运行,云不就是一个巨大的 API 吗?我们可以轻松地自动化创建任何集群大小或我们想要的任何 ec2 实例类型。

我们将在 7 种不同的集群配置上运行所有这些测试,并使用三种不同的存储卷类型(io1、gp2、st1)。

集群

  • 3 个节点,c5.9xlarge,36 个 vCPU,72 GB 内存 = 108 个 vCPU
  • 3 个节点,c5.4xlarge,16 个 vCPU,32GB 内存 = 48 个 vCPU
  • 5 个节点,c5.4xlarge,16 个 vCPU,32GB 内存 = 80 个 vCPU
  • 7 个节点,c5.4xlarge,16 个 vCPU,32GB 内存 = 112 个 vCPU
  • 5 个节点,c5.2xlarge,8 个 vCPU,16 GB 内存 = 40 个 vCPU
  • 7 个节点,c5.2xlarge,8 个 vCPU,16 GB 内存 = 56 个 vCPU
  • 9 个节点,c5.2xlarge,8 个 vCPU,16 GB 内存 = 72 个 vCPU

c5.9xlarge 可以被认为是非常大的虚拟机,它绝对是您会使用的最大的虚拟机。c5.4xlarge 可以被认为是大型虚拟机,而 c5.2xlarge 是中型实例。这是一个相当密集的工作负载,这就是为什么我们将这些大型实例类型包含在分析中。许多不太密集的工作负载将适用于较小的实例类型,例如具有 4 个 vCPU 的 c5.xlarge 或 c5.large。如果内存成为这些计算优化实例上的问题,则更大的内存实例类型(m5、r5)也是一种选择。

  • io1(预配置 iops SSD),200GB,10000 IOPS,最大 500MiB/s = 每月 725 美元
  • gp2(通用 SSD),1000GB,3000 IOPS,最大 250 MiB/s = 每月 100 美元
  • st1(高吞吐量 HDD),7000GB,基线 280 MB/s,最大 500MiB/s = 每月 315 美元

io1 的尺寸具有大量的 IOP,这很昂贵。部分选择它是为了展示更昂贵的磁盘如何在大小调整分析中发挥作用。您将从案例研究中看到,我们可以选择 IOP 较少的 io1,这将更具成本效益。

我们选择大型 gp2 是因为较小的卷会获得突发积分,这可能会让您感到惊讶。同样,我们也选择了 7TB HDD,也是因为突发积分。此大小仍然具有突发,但这些工作负载不会过多地深入突发,并且是成本的平衡(此大小将管理 2 小时的高峰期)。对于强度较低的工作负载,我们可以选择更小的尺寸并节省一些资金。

这是一个 1TB HDD 的测试,其中突发积分已用完。

Fig 1. EBS volume burst credits run out.
图 1. EBS 卷突发积分用完。

每月成本(按需定价)

io1 SSD

成本是:虚拟机 + 卷 = 总计

  • 3 个节点,c5.9xlarge = 36 个 vCPU,每月成本 3300 美元 + 2175 美元 = 5475 美元
  • 3 个节点,c5.4xlarge = 16 个 vCPU,每月成本 1468 美元 + 2175 美元 = 3643 美元
  • 5 个节点,c5.4xlarge = 16 个 vCPU,每月成本 2445 美元 + 3625 美元 = 6070 美元
  • 7 个节点,c5.4xlarge = 16 个 vCPU,每月成本 4123 美元 + 5075 美元 = 9198 美元
  • 5 个节点,c5.2xlarge = 8 个 vCPU,每月成本 1225 美元 + 3625 美元 = 4850 美元
  • 7 个节点,c5.2xlarge = 8 个 vCPU,每月成本 1715 美元 + 5075 美元 = 6790 美元
  • 9 个节点,c5.2xlarge = 8 个 vCPU,每月成本 2205 美元 + 6525 美元 = 8730 美元

gp2 SSD

成本是:虚拟机 + 卷 = 总计

  • 3 个节点,c5.9xlarge = 36 个 vCPU,每月成本 3300 美元 + 300 美元 = 3600 美元
  • 3 个节点,c5.4xlarge = 16 个 vCPU,每月成本 1468 美元 + 300 美元 = 1768 美元
  • 5 个节点,c5.4xlarge = 16 个 vCPU,每月成本 2445 美元 + 500 美元 = 2945 美元
  • 7 个节点,c5.4xlarge = 16 个 vCPU,每月成本 4123 美元 + 700 美元 = 4823 美元
  • 5 个节点,c5.2xlarge = 8 个 vCPU,每月成本 1225 美元 + 500 美元 = 1725 美元
  • 7 个节点,c5.2xlarge = 8 个 vCPU,每月成本 1715 美元 + 700 美元 = 2415 美元
  • 9 个节点,c5.2xlarge = 8 个 vCPU,, 每月成本 2205 美元 + 900 美元 = 3105 美元

st1 HDD

成本是:虚拟机 + 卷 = 总计

  • 3 个节点,c5.9xlarge = 36 个 vCPU,每月成本 3300 美元 + 945 美元 = 4245 美元
  • 3 个节点,c5.4xlarge = 16 个 vCPU,每月成本 1468 美元 + 945 美元 = 2413 美元
  • 5 个节点,c5.4xlarge = 16 个 vCPU,每月成本 2445 美元 + 1575 美元 = 4020 美元
  • 7 个节点,c5.4xlarge = 16 个 vCPU,每月成本 4123 美元 + 2205 美元 = 6328 美元
  • 5 个节点,c5.2xlarge = 8 个 vCPU,每月成本 1225 美元 + 1575 美元 = 2800 美元
  • 7 个节点,c5.2xlarge = 8 个 vCPU,每月成本 1715 美元 + 2205 美元 = 3920 美元
  • 9 个节点,c5.2xlarge = 8 个 vCPU,, 每月成本 2205 美元 + 2835 美元 = 5040 美元

我们不包括数据传输成本。

我们看到选择 gp2 实际上是我们最便宜的选择。当然,st1 HDD 的每 GB 成本只有一半,但如果我们选择更小的尺寸,我们就无法实现更高的强度吞吐量。因此,对于我们的需求来说,SSD 可能是最具成本效益的选择。当然,它永远无法处理超过 250 MiB/s 的速度,因此如果这是限制因素,那么您将被迫选择昂贵的 io1 或 st1。

案例研究

在接下来的文章中,我们将使用镜像队列和 quorum 队列执行此大小调整分析。

可能适用于您的工作负载的其他测试

还有一些您可能希望根据您的工作负载运行的更多测试。例如

  • 您可能希望在峰值负载下运行长时间运行的测试。这两个案例研究中的测试时间很短 - 在 10 分钟到 1 小时 40 分钟之间。如果您确定了特定的强度和集群配置,您可以尝试运行 24 小时以确保您的选择。显然,如果您有突发网络/磁盘,那么如果您在峰值时测试这么长时间,这可能会影响结果。
  • 您可能会定期从批处理作业中收到非常大的消息,您想对其进行测试。顺便说一句,我们建议对大型消息使用像 s3 这样的对象存储(将它的 URI 作为消息传递)。
  • 您可能想通过完全停止并启动集群来测试积压的恢复时间。
  • 您可能有可变数量的客户端连接到您的集群。使用正常到最坏情况的连接客户端数量测试您的候选集群大小。
  • 连接变更(连接的打开和关闭)也会给集群带来压力。如果您有可变数量的连接变更,请使用正常情况和最坏情况进行测试。另请参阅 /docs/networking.html#tuning-for-large-number-of-connections-tcp-buffer-size
  • 您可能有可变数量的队列。使用正常到最坏情况的队列数量测试您的候选集群大小。

最终想法

您在大小调整上投入的精力可能与您在系统中对 RabbitMQ 的依赖程度以及如果它未能提供必要的性能所涉及的成本有关。如果您有一个不重要的小工作负载,那么您可能不希望在大小调整上花费太多时间。尝试几个小的选项并进行监控。

如果您有较大的工作负载或业务关键型工作负载,那么花时间进行容量规划和正确的大小调整可能会在以后为您节省更多损失的时间和痛苦。

花时间查看 quorum 队列和镜像队列的案例研究,但如果您没有时间,那么这里有一些提炼成单个部分的指南。

高可用性 (HA) 是一项常见要求,也是我们使用复制队列(quorum、镜像)的原因。我们不想丢失消息,并且我们希望即使在发生故障时也能保持持续可用性。不要忘记,容量规划对于实现这些目标也至关重要。

大小调整是在理想和不利条件下运行您的工作负载或工作负载模拟。峰值负载通常是企业赚最多钱的时候,也是最有可能发生不利条件的时候。根据不利条件进行大小调整是正确进行大小调整的关键部分。

不利条件,如果 RabbitMQ 大小调整得当,仍然可以有效运行,包括

  • 代理丢失(磁盘故障、虚拟机重启、网络分区)
  • 队列积压(由消费者速度减慢或发布峰值引起)
  • 大量 TCP 连接
  • 大量队列

在这些事情中,代理丢失可能是 RabbitMQ 最不紧张的事情。RabbitMQ 最难处理的事情之一是非常大的队列积压。在我们的案例研究中,我们看到通过适当的大小调整,RabbitMQ 可以在巨大的积压情况下处理这种高吞吐量的工作负载,但仅限于最大的集群。较小的集群在理想条件下表现良好,但在队列开始积压时迅速恶化。

如果您已经自动化了生产和 QA 环境的部署,那么测试不同的虚拟机大小和数量应该足够简单。如果您可以使用您的实际应用程序运行这些大小调整测试,那么这很可能会给您最准确的结果。如果使用您自己的应用程序来生成负载太多,那么请考虑设计一个尽可能接近真实世界的合成工作负载。

案例研究包括 PerfTest 命令,并且还有 这篇文章 提供了有关运行性能测试的指导和选项。

我希望这份大小调整指南对您有所帮助,并帮助 RabbitMQ 成为您架构中坚如磐石的一部分。

© . All rights reserved.