集群大小案例研究 - 镜像队列 第 1 部分
在本大小系列的第一个帖子中,我们介绍了工作负载、集群和存储卷的配置,它们都部署在 AWS ec2 上。在本帖子中,我们将对镜像队列运行大小分析。
我们大小分析的第一阶段将评估每个集群和存储卷可以轻松处理的强度,以及哪些强度过高。
所有测试都使用以下策略
- ha-mode: exactly
- ha-params: 2
- ha-sync-mode: manual
理想条件 - 增长强度测试
在之前的帖子中,我们讨论了运行基准测试的选项。您可以使用以下命令在这些强度下运行此工作负载。
bin/runjava com.rabbitmq.perf.PerfTest \
-H amqp://guest:guest@10.0.0.1:5672/%2f,amqp://guest:guest@10.0.0.2:5672/%2f,amqp://guest:guest@10.0.0.3:5672/%2f \
-z 1800 \
-f persistent \
-q 1000 \
-c 1000 \
-ct -1 \
--rate 50 \
--size 1024 \
--queue-pattern 'perf-test-%d' \
--queue-pattern-from 1 \
--queue-pattern-to 100 \
--producers 200 \
--consumers 200 \
--consumer-latency 10000 \
--producer-random-start-delay 30
只需将 --rate 参数更改为每个测试所需的速率,并记住它是每个发布者的速率,而不是总的合并速率。由于消费者处理时间(消费者延迟)设置为 10 毫秒,因此我们还需要为更高的发布速率增加消费者数量。
在运行 PerfTest 之前,您需要创建一个策略,将创建的队列变成镜像队列,其中一个为主队列,镜像数量为要测试的数量。
io1 - 高性能 SSD
不同的集群能够达到不同的强度,但除一个测试外,所有测试的端到端延迟的第 99 个百分位都保持在 1 秒以内。
大多数测试的限制因素是 CPU,因此配置 CPU 数量最多的集群表现最好不足为奇。有趣的是,3 节点 36 个 vCPU 集群(3x36)的总 vCPU 数量排名第二,但表现远低于 7x8 个 vCPU 集群。实际上,3x36 集群的 CPU 利用率从未超过 50%,似乎 Erlang 无法有效地利用每个代理上的所有 36 个 vCPU(稍后详细介绍)。
磁盘吞吐量远未达到容量,但所有配置的 IOPS 都达到了 8000-9000,写入大小约为 5-7 KB。网络带宽保持在 1 Gbps 以下,低于所有虚拟机的限制。
吞吐量最低的集群(3x16)
吞吐量最高的集群(7x16)
见解:性能较低的 3x16 集群的磁盘写入吞吐量略高于性能最佳的 7x16 集群。这是因为如果消息在执行 fsync 之前已经被消费,则不会将其持久保存到磁盘。因此,当消费者跟上时,磁盘写入量会更低。如果我们查看 25k msg/s 测试(这是两个集群都能处理的最高速率),我们会发现 3x16 集群的第 95 个百分位延迟约为 250 毫秒,而 7x16 集群的第 95 个百分位延迟约为 4 毫秒。fsync 约每 200 毫秒发生一次。因此,性能更高的集群执行的写入次数更少。
匹配目标吞吐量的排行榜
每个集群大小所能达到的最高吞吐量,它准确地提供了目标速率。
- 集群:7 个节点,16 个 vCPU(c5.4xlarge)。速率:65k msg/s
- 集群:5 个节点,16 个 vCPU(c5.4xlarge)。速率:45k msg/s
- 集群:9 个节点,8 个 vCPU(c5.2xlarge)。速率:45k msg/s
- 集群:7 个节点,8 个 vCPU(c5.2xlarge)。速率:40k msg/s
- 集群:3 个节点,36 个 vCPU(c5.9xlarge)。速率:30k msg/s
- 集群:5 个节点,8 个 vCPU(c5.2xlarge)。速率:20k msg/s
- 集群:3 个节点,16 个 vCPU(c5.4xlarge)。速率:20k msg/s
我们可以看到,向上和向外扩展的中庸之道为我们提供了最佳吞吐量,但向外扩展也表现相当好。向上扩展效果不佳。
每月每 1000 mgs/s 成本的排行榜,以最高吞吐量为准。
- 集群:5 个节点,16 个 vCPU。成本:134 美元(45k msg/s)
- 集群:7 个节点,16 个 vCPU。成本:140 美元(65k msg/s)
- 集群:7 个节点,8 个 vCPU。成本:170 美元(40k msg/s)
- 集群:3 个节点,16 个 vCPU。成本:182 美元(20k msg/s)
- 集群:3 个节点,36 个 vCPU。成本:182 美元(30k msg/s)
- 集群:9 个节点,8 个 vCPU。成本:194 美元(45k msg/s)
- 集群:5 个节点,8 个 vCPU。成本:242 美元(20k msg/s)
每月每 1000 条消息成本的排行榜,以目标速率 30k msg/s 为准。
- 集群:3 个节点,36 个 vCPU。成本:183 美元
- 集群:5 个节点,16 个 vCPU。成本:202 美元
- 集群:7 个节点,8 个 vCPU。成本:226 美元
- 集群:9 个节点,8 个 vCPU。成本:291 美元
- 集群:7 个节点,16 个 vCPU。成本:307 美元
虽然使用更小的虚拟机进行向外扩展具有不错的吞吐量,但由于我们的磁盘是最昂贵的项目,因此这种方法受到削弱。由于磁盘价格昂贵,因此最具成本效益的集群是实例最少的集群,但是,这个 3x36 集群在理想条件测试中只是勉强达到峰值,在更困难的测试中可能无法承受。因此,如果我们忽略 3x36 集群,最具成本效益的方法是向上和向外扩展的中庸之道。
我们真的需要那些昂贵的 io1 SSD 吗?我们不需要它们来实现 IO 吞吐量,但那些 10000 IOPS 几乎完全被利用。3000 IOP 的 gp2 是否能处理更高的强度?
gp2 - 通用 SSD
同样,不同的集群能够达到不同的吞吐量,但所有测试的端到端延迟都在要求范围内。
使用 gp2 卷,我们有了一个新的赢家:9x8 集群,其次是 7x8 集群。7x16 和 5x16 在达到并超过其最高容量后,出现了一些吞吐量波动。最后两个排名相同:3x36 集群和 3x16 集群。
那么 RabbitMQ 如何处理较低的 IOPs 卷?
吞吐量最低的集群(3x16)
我们从 5000 msg/s 速率开始,一直到上限,都达到了 3000 IOPs 限制。随着测试的进行,为了应对更大的磁盘吞吐量,IO 大小会增加。因此,看来我们并不需要那么多 IOPS。
吞吐量最高的集群(9x8)
性能最高的集群也是同样的情况 - RabbitMQ 调整了可用的较低 IOPs。
匹配目标吞吐量的排行榜
- 集群:9 个节点,8 个 vCPU(c5.2xlarge)。速率:65k msg/s
- 集群:7 个节点,8 个 vCPU(c5.2xlarge)。速率:50k msg/s
- 集群:7 个节点,16 个 vCPU(c5.4xlarge)。速率:50k msg/s
- 集群:5 个节点,16 个 vCPU(c5.4xlarge)。速率:40k msg/s
- 集群:3 个节点,36 个 vCPU(c5.9xlarge)。速率:35k msg/s
- 集群:5 个节点,8 个 vCPU(c5.2xlarge)。速率:35k msg/s
- 集群:3 个节点,16 个 vCPU(c5.4xlarge)。速率:25k msg/s
这次,向外扩展显然是最有效的方法。向上扩展效果不佳。
每月每 1000 条消息成本的排行榜,以最高吞吐量为准。
- 集群:9 个节点,8 个 vCPU。成本:48 美元(65k msg/s)
- 集群:7 个节点,8 个 vCPU。成本:48 美元(50k msg/s)
- 集群:5 个节点,8 个 vCPU。成本:49 美元(35k msg/s)
- 集群:3 个节点,16 个 vCPU。成本:71 美元(25k msg/s)
- 集群:5 个节点,16 个 vCPU。成本:74 美元(40k msg/s)
- 集群:7 个节点,16 个 vCPU。成本:96 美元(50k msg/s)
- 集群:3 个节点,36 个 vCPU。成本:103 美元(35k msg/s)
就每单位最高吞吐量成本而言,排序为:_核心数量降序,节点数量降序_。
每月每 1000 条消息成本的排行榜,以目标速率 30k msg/s 为准。
- 集群:5 个节点,8 个 vCPU。成本:58 美元
- 集群:7 个节点,8 个 vCPU。成本:81 美元
- 集群:5 个节点,16 个 vCPU。成本:98 美元
- 集群:9 个节点,8 个 vCPU。成本:104 美元
- 集群:3 个节点,36 个 vCPU。成本:120 美元
- 集群:7 个节点,16 个 vCPU。成本:161 美元
在我们的目标速率 30k msg/s 下,5x8 最好。结论是,使用更小的虚拟机进行向外扩展既可以提高性能,也可以提高成本效益。原因是 gp2 卷相对便宜,并且不会像使用昂贵的 io1 卷那样因为向外扩展而受到惩罚。
st1 - HDD
到目前为止,我们已经看到 RabbitMQ 通过根据需要调整磁盘操作来利用可用的 IOPS。HDD 适用于具有较低 IOPs 的大型顺序工作负载,那么 RabbitMQ 是否能够再次调整其磁盘操作,以便执行更少但更大的磁盘操作?让我们拭目以待。
从吞吐量来看,HDD 在峰值吞吐量方面表现最好,实际上达到了 70k msg/s 的最高强度。端到端延迟表现出不同的模式。对于 SSD,延迟从很小开始,然后随着强度的增加而增长。但 HDD 从更高的延迟开始,并且以更低的速度增长。
让我们看看 RabbitMQ 如何使用可用的 IOPS。
吞吐量最低的集群(3x16)
我们现在下降到 500-600 IOPS,平均写入大小接近 50kb(忽略初始峰值)。更少但更大的 IO 操作。IO 延迟更高。我们从 0.5ms(io1)、2ms(gp2)到 10ms(st1)的延迟,这很可能是 IO 大小和存储驱动器执行随机 IO 速度的组合。在下面,我们将比较三种磁盘类型的端到端延迟。
峰值吞吐量集群 (9x8)
吞吐量排行榜
只有三种尺寸能够达到目标,其他尺寸始终不足,即使它们的吞吐量在每次测试中都攀升。我们可能可以通过不同的发布者确认飞行限制来提高吞吐量,更高的限制可能对延迟更高的 HDD 有利。
能够达到目标的获胜者是
- 集群:9 节点,8 个 vCPU (c5.2xlarge)。速率:70k msg/s
- 集群:7 节点,16 个 vCPU (c5.4xlarge)。速率:65k msg/s
- 集群:7 节点,8 个 vCPU (c5.2xlarge)。速率:55k msg/s
其余集群在每次测试中都未能达到目标,但在测试过程中仍然显示出更高的吞吐量
- 集群:5 节点,16 个 vCPU (c5.4xlarge)。速率:55k msg/s
- 集群:5 节点,8 个 vCPU (c5.2xlarge)。速率:43k msg/s
- 集群:3 个节点,36 个 vCPU(c5.9xlarge)。速率:35k msg/s
- 集群:3 节点,16 个 vCPU (c5.4xlarge)。速率:29k msg/s
对于 HDD,关键是横向扩展,而不是纵向扩展。
每月每 1000 条消息的成本排行榜,以其峰值速率计算。
- 集群:5 节点,8 个 vCPU。成本:$65 (43k msg/s)
- 集群:7 节点,8 个 vCPU。成本:$71 (55k msg/s)
- 集群:9 节点,8 个 vCPU。成本:$72 (70k msg/s)
- 集群:5 节点,16 个 vCPU。成本:$73 (55k msg/s)
- 集群:3 节点,16 个 vCPU。成本:$83 (29k msg/s)
- 集群:7 节点,16 个 vCPU。成本:$97 (65k msg/s)
- 集群:3 节点,36 个 vCPU。成本:$121 (35k msg/s)
每月每 1000 条消息成本的排行榜,以目标速率 30k msg/s 为准。
- 集群:5 节点,8 个 vCPU。成本:$93
- 集群:7 节点,8 个 vCPU。成本:$131
- 集群:5 节点,16 个 vCPU。成本:$134
- 集群:3 节点,36 个 vCPU。成本:$142
- 集群:9 节点,8 个 vCPU。成本:$168
- 集群:7 节点,16 个 vCPU。成本:$211
从峰值吞吐量来看,较小的 VM 显然最具成本效益。但考虑到 30k msg/s 的目标,横向和纵向扩展的折衷方案显示出最佳结果。横向扩展对性能和成本最有利(st1 卷略贵)之间再次存在一些冲突。因此,折衷方案获胜。
端到端延迟和三种卷类型
在这些测试中,我们将端到端延迟视为消息从发布到消费的时间间隔。如果我们查看 30k msg/s 的目标速率和 7x16 集群类型,我们将看到
io1
gp2
st1
我们看到 io1 在 95 个百分位之前提供了最佳延迟,之后它或多或少与 gp2 相匹配。st1 HDD 显示出更高的延迟,但仍然在我们 1 秒的目标范围内。
CPU 利用率和 36 个 vCPU 的 VM
在 8 个和 16 个 vCPU(CPU 线程)实例中,CPU 似乎是瓶颈。一旦 CPU 达到 90% 以上,我们就看不到吞吐量有任何进一步的增加。然而,36 个 vCPU 的实例往往始终看起来像这样
CPU 利用率和 Erlang 并不总是直截了当。Erlang 调度程序在认为这样做更有效时会进行忙等待。这意味着调度程序不会休眠,而是在忙循环中等待,在等待新工作时使用 CPU。这可能使 Erlang 应用程序看起来正在执行大量工作,使用 CPU,但实际上它只是在等待工作。
在这种情况中,36 个 vCPU 只是浪费。我们已经看到,与横向扩展的较小 VM 相比,它们更昂贵,并且提供的结果较差。
增加强度基准测试 - 结论
到目前为止,结论是
- 只有当我们真正关心端到端延迟时,昂贵的 io1 才值得。
- 廉价的 gp2 提供了性能和成本的最佳组合,是大多数工作负载的最佳选择。请记住,我们使用了 1TB 的大小,该大小没有突发 IOPS,并且有 250 MiBs 的限制(我们从未达到过)。
- 对于廉价的存储卷,横向扩展较小的 8 个 vCPU 的 VM 在成本效益和性能方面都是最佳选择。
- 对于昂贵的卷,横向扩展和纵向扩展的折衷方案是最具成本效益的。
- CPU 利用率似乎是 16 个和 8 个 vCPU 的限制因素。大型的 36 个 vCPU 实例没有超过 60% 的利用率,但也没有达到磁盘或网络限制。Erlang 只是无法有效地利用这么多核心。
每月每 1000 条 msg/s 的成本最高的 5 种配置,用于 30k msg/s 吞吐量
- 集群:5 节点,8 个 vCPU,gp2 SDD。成本:$58
- 集群:7 节点,8 个 vCPU,gp2 SDD。成本:$81
- 集群:5 节点,8 个 vCPU,st1 HDD。成本:$93
- 集群:5 节点,16 个 vCPU,gp2 SDD。成本:$98
- 集群:9 节点,8 个 vCPU,gp2 SDD。成本:$104
我们只在理想条件下进行了测试...
我们从 21 种不同的集群配置中收集了大量数据,这些配置在 15 种不同的工作负载强度下运行。我们认为,到目前为止,我们应该选择一个中等或大型的集群,该集群在廉价的 gp2 卷上运行较小的 VM。但这只是测试了队列为空或接近空的情况,即 RabbitMQ 以峰值性能运行的情况。接下来,我们将运行更多测试,确保即使在代理丢失和队列积压发生的情况下,我们选择的集群大小也能继续提供我们所需的性能。 下一步 我们测试弹性。