AMQP 1.0 基准测试
这篇博客文章表明,RabbitMQ 4.0 中的 原生 AMQP 1.0 与 RabbitMQ 3.13 中的 AMQP 1.0 相比,在性能和可伸缩性方面有了显著的提升。
此外,这篇博客文章建议,在 RabbitMQ 4.0 中,AMQP 1.0 的性能可能略优于 AMQP 0.9.1。
设置
以下设置适用于本博文中的所有基准测试
- Intel NUC 11
- 8 个 CPU 核心
- 32 GB RAM
- Ubuntu 22.04
- 单节点 RabbitMQ 服务器
- 服务器使用(仅)3 个调度器线程运行(通过 运行时标志 设置为
+S 3) - Erlang/OTP 27.0.1
- 客户端和服务器运行在同一台机器上
我们使用撰写本文时最新的 RabbitMQ 版本
应用了以下 advanced.config
[
{rabbit, [
{loopback_users, []}
]},
{rabbitmq_management_agent, [
{disable_metrics_collector, true}
]}
].
rabbitmq_management_agent 插件中禁用了指标收集。对于生产环境,Prometheus是推荐的选项。
RabbitMQ 服务器的启动方式如下
make run-broker \
TEST_TMPDIR="$HOME/scratch/rabbit/test" \
RABBITMQ_CONFIG_FILE="$HOME/scratch/rabbit/advanced.config" \
PLUGINS="rabbitmq_prometheus rabbitmq_management rabbitmq_amqp1_0" \
RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="+S 3"
rabbitmq_amqp1_0 插件在 RabbitMQ 4.0 中是一个 空操作插件。
AMQP 1.0 基准测试在 Docker 容器中运行 quiver。
$ docker run -it --rm --add-host host.docker.internal:host-gateway ssorj/quiver:latest
bash-5.1# quiver --version
quiver 0.4.0-SNAPSHOT
经典队列
本节测试 经典队列。
我们声明一个名为 my-classic-queue 的经典队列。
deps/rabbitmq_management/bin/rabbitmqadmin declare queue \
name=my-classic-queue queue_type=classic durable=true
4.0 版本中的 AMQP 1.0
客户端发送和接收 100 万条消息。每条消息包含 12 字节的数据。接收方一次性补充 200 个链接信用额度。
# quiver //host.docker.internal//queues/my-classic-queue \
--durable --count 1m --duration 10m --body-size 12 --credit 200
RESULTS
Count ............................................. 1,000,000 messages
Duration ............................................... 10.1 seconds
Sender rate .......................................... 99,413 messages/s
Receiver rate ........................................ 99,423 messages/s
End-to-end rate ...................................... 99,413 messages/s
Latencies by percentile:
0% ........ 0 ms 90.00% ........ 1 ms
25% ........ 1 ms 99.00% ........ 2 ms
50% ........ 1 ms 99.90% ........ 2 ms
100% ........ 9 ms 99.99% ........ 9 ms
3.13 版本中的 AMQP 1.0
# quiver //host.docker.internal//amq/queue/my-classic-queue \
--durable --count 1m --duration 10m --body-size 12 --credit 200
RESULTS
Count ............................................. 1,000,000 messages
Duration ............................................... 45.9 seconds
Sender rate .......................................... 43,264 messages/s
Receiver rate ........................................ 21,822 messages/s
End-to-end rate ...................................... 21,790 messages/s
Latencies by percentile:
0% ....... 67 ms 90.00% .... 24445 ms
25% .... 23056 ms 99.00% .... 24780 ms
50% .... 23433 ms 99.90% .... 24869 ms
100% .... 24873 ms 99.99% .... 24873 ms
与 RabbitMQ 3.13 进行的相同基准测试的吞吐量降低了 4.5 倍。
详细的测试执行
---------------------- Sender ----------------------- --------------------- Receiver ---------------------- --------
Time [s] Count [m] Rate [m/s] CPU [%] RSS [M] Time [s] Count [m] Rate [m/s] CPU [%] RSS [M] Lat [ms]
----------------------------------------------------- ----------------------------------------------------- --------
2.1 130,814 65,342 8 79.1 2.1 3,509 1,753 1 7.5 777
4.1 206,588 37,849 6 79.1 4.1 5,995 1,242 0 7.5 2,458
6.1 294,650 43,987 6 79.1 6.1 9,505 1,753 1 7.5 5,066
8.1 360,184 32,734 5 79.4 8.1 13,893 2,194 0 7.5 6,190
10.1 458,486 49,102 6 79.4 10.1 15,793 950 1 7.5 9,259
12.1 524,020 32,734 5 79.4 12.1 21,644 2,923 1 7.5 11,163
14.1 622,322 49,102 5 79.4 14.1 25,154 1,753 1 7.5 13,451
16.1 687,856 32,734 4 79.4 16.1 27,639 1,241 1 7.5 15,246
18.1 786,158 49,102 6 81.0 18.1 30,124 1,241 1 7.5 17,649
20.1 884,460 49,102 6 81.0 20.1 32,610 1,242 1 7.5 19,408
22.1 949,994 32,734 4 81.0 22.1 35,535 1,462 0 7.5 21,293
24.1 999,912 24,934 4 81.8 24.1 38,167 1,315 1 7.5 23,321
26.1 999,974 31 2 0.0 26.1 117,745 39,749 11 7.5 24,475
- - - - - 28.1 202,589 42,380 11 7.5 24,364
- - - - - 30.1 292,554 44,938 13 7.5 24,244
- - - - - 32.1 377,691 42,526 15 7.5 23,955
- - - - - 34.1 469,704 45,961 14 7.5 23,660
- - - - - 36.1 555,719 42,965 12 7.5 23,463
- - - - - 38.1 649,048 46,618 12 7.5 23,264
- - - - - 40.1 737,696 44,280 15 7.5 23,140
- - - - - 42.1 826,491 44,353 15 7.5 23,100
- - - - - 44.1 917,187 45,303 16 7.5 23,066
- - - - - 46.1 999,974 41,394 14 0.0 22,781
4.0 版本中的 AMQP 0.9.1
对于我们的 AMQP 0.9.1 基准测试,我们使用 PerfTest。我们尝试对我们之前的 AMQP 1.0 基准测试进行一次公平的比较。
由于 AMQP 1.0 的 /queues/:queue 目标地址发送到默认交换器,因此我们也通过 AMQP 0.9.1 发送给默认交换器。由于我们在 AMQP 1.0 中使用了持久性消息,因此我们在 AMQP 0.9.1 中设置了 persistent 标志。由于 RabbitMQ 在消息无法路由时会以已释放结果进行结算,因此我们在 AMQP 0.9.1 中设置了 mandatory 标志。由于 RabbitMQ v4.0.0-beta.5 使用默认的 rabbit.max_link_credit 为 128,当剩余信用额度低于 0.5 * 128 时,会授予发送客户端额外的 128 个信用额度,我们将 AMQP 0.9.1 发布者配置为一次最多未确认消息 1.5 * 128 = 192 条。由于我们在上一次运行中使用了 200 个链接信用额度,因此我们将 AMQP 0.9.1 消费者配置为预取 200。
$ java -jar target/perf-test.jar \
--predeclared --exchange amq.default \
--routing-key my-classic-queue --queue my-classic-queue \
--flag persistent --flag mandatory \
--pmessages 1000000 --size 12 --confirm 192 --qos 200 --multi-ack-every 200
id: test-151706-485, sending rate avg: 88534 msg/s
id: test-151706-485, receiving rate avg: 88534 msg/s
id: test-151706-485, consumer latency min/median/75th/95th/99th 99/975/1320/1900/2799 µs
id: test-151706-485, confirm latency min/median/75th/95th/99th 193/1691/2113/2887/3358 µs
摘要
仲裁队列
本节测试 法定人数队列。
我们声明一个名为 my-quorum-queue 的法定人数队列。
deps/rabbitmq_management/bin/rabbitmqadmin declare queue \
name=my-quorum-queue queue_type=quorum durable=true
流控配置
为了最高的数据安全性,法定人数队列会对所有Ra 命令执行fsync,包括:
在法定人数队列向发布者确认收到消息之前,它会确保任何文件修改已刷新到磁盘,即使 RabbitMQ 节点在之后不久崩溃,数据也是安全的。
我的 Linux 盒子的 SSD 速度很慢,每次 fsync 需要 5-15 毫秒。由于我们希望在不被廉价磁盘限制的情况下比较 AMQP 协议实现,因此本节中的测试会增加流控设置。
advanced.config
[
{rabbit, [
{loopback_users, []},
%% RabbitMQ internal flow control for AMQP 0.9.1
%% Default: {400, 200}
{credit_flow_default_credit, {5000, 2500}},
%% Maximum incoming-window of AMQP 1.0 session.
%% Default: 400
{max_incoming_window, 5000},
%% Maximum link-credit RabbitMQ grants to AMQP 1.0 sender.
%% Default: 128
{max_link_credit, 2000},
%% Maximum link-credit RabbitMQ AMQP 1.0 session grants to sending queue.
%% Default: 256
{max_queue_credit, 5000}
]},
{rabbitmq_management_agent, [
{disable_metrics_collector, true}
]}
].
此配置允许在 RabbitMQ 调用 fsync 之前批量处理更多 Ra 命令。对于生产用例,我们推荐企业级高性能磁盘,它们的 fsync 速度更快,在这种情况下,可能不需要增加流控设置。
RabbitMQ 流控设置权衡了稳定性与性能
- 较低的值可确保生产环境的稳定性。
- 较高的值可能为单个连接带来更高的性能,但在许多连接并发发布大型消息时可能导致更高的内存峰值。
RabbitMQ 使用保守的流控默认设置,优先考虑生产环境的稳定性而非性能基准测试。
4.0 版本中的 AMQP 1.0
# quiver //host.docker.internal//queues/my-quorum-queue \
--durable --count 1m --duration 10m --body-size 12 --credit 5000
RESULTS
Count ............................................. 1,000,000 messages
Duration ............................................... 12.0 seconds
Sender rate .......................................... 83,459 messages/s
Receiver rate ........................................ 83,396 messages/s
End-to-end rate ...................................... 83,181 messages/s
Latencies by percentile:
0% ........ 9 ms 90.00% ....... 47 ms
25% ....... 27 ms 99.00% ....... 61 ms
50% ....... 35 ms 99.90% ....... 76 ms
100% ....... 81 ms 99.99% ....... 81 ms
默认流控设置
上一个基准测试在 ra_log_wal 模块(实现了 Raft 预写日志)中调用了 1,244 次 fsync。
使用默认流控设置的相同基准测试调用 fsync 15,493 次,导致吞吐量显着降低。
# quiver //host.docker.internal//queues/my-quorum-queue \
--durable --count 1m --duration 10m --body-size 12 --credit 5000
RESULTS
Count ............................................. 1,000,000 messages
Duration .............................................. 100.2 seconds
Sender rate ........................................... 9,986 messages/s
Receiver rate ......................................... 9,987 messages/s
End-to-end rate ....................................... 9,983 messages/s
Latencies by percentile:
0% ....... 10 ms 90.00% ....... 24 ms
25% ....... 14 ms 99.00% ....... 30 ms
50% ....... 18 ms 99.90% ....... 38 ms
100% ....... 55 ms 99.99% ....... 47 ms
平均每次 fsync 花费 5.9 毫秒。
(15,493 - 1,244) * 5.9 ms = 84 seconds
因此,此基准测试在默认流控设置下,执行 fsync 比上一个增加流控设置的基准测试耗时长 84 秒。这表明企业级高性能磁盘对于获得法定人数队列的最佳结果有多么关键。对于您的生产工作负载,我们建议使用 fsync 延迟较低的磁盘,而不是调整 RabbitMQ 流控设置。
值得注意的是,Raft WAL 日志由给定 RabbitMQ 节点上的所有法定人数队列副本共享。这意味着当有几十个法定人数队列和数百个连接时,ra_log_wal 会自动将多个 Ra 命令(操作)批量处理到一次 fsync 调用中。因此,当节点上的流量增加时,将单个 Ra 命令刷新到磁盘的平均成本会降低。我们的基准测试以单个连接尽可能快地运行,这在一定程度上是人为的。
3.13 版本中的 AMQP 1.0
# quiver //host.docker.internal//amq/queue/my-quorum-queue \
--durable --count 1m --duration 10m --body-size 12 --credit 5000
---------------------- Sender ----------------------- --------------------- Receiver ---------------------- --------
Time [s] Count [m] Rate [m/s] CPU [%] RSS [M] Time [s] Count [m] Rate [m/s] CPU [%] RSS [M] Lat [ms]
----------------------------------------------------- ----------------------------------------------------- --------
2.1 163,582 81,709 11 84.2 2.1 29,548 14,759 3 7.5 840
4.1 336,380 86,356 12 185.3 4.1 29,840 146 0 7.5 2,331
6.1 524,026 93,729 14 328.0 6.1 29,840 0 0 7.5 0
8.1 687,864 81,837 11 462.3 8.1 31,302 730 1 7.5 6,780
10.1 884,470 98,303 14 605.4 10.1 31,447 72 0 7.5 7,897
12.1 999,924 57,669 7 687.5 12.1 31,447 0 0 7.5 0
14.1 999,924 0 0 687.5 14.1 31,447 0 0 7.5 0
16.1 999,924 0 0 687.5 16.1 31,447 0 1 7.5 0
18.1 999,924 0 1 688.3 18.1 31,447 0 0 7.5 0
receiver timed out
20.1 999,924 0 0 688.3 20.1 31,447 0 0 7.5 0
RabbitMQ 3.13 无法处理此工作负载,基准测试失败。
默认流控设置
基准测试在默认流控设置下也失败。
# quiver //host.docker.internal//amq/queue/my-quorum-queue \
--durable --count 1m --duration 10m --body-size 12 --credit 5000
---------------------- Sender ----------------------- --------------------- Receiver ---------------------- --------
Time [s] Count [m] Rate [m/s] CPU [%] RSS [M] Time [s] Count [m] Rate [m/s] CPU [%] RSS [M] Lat [ms]
----------------------------------------------------- ----------------------------------------------------- --------
2.1 130,814 65,342 9 70.0 2.1 26,915 13,437 6 7.5 1,213
4.1 196,348 32,718 5 70.2 4.1 28,084 584 0 7.5 3,093
6.1 261,882 32,734 7 70.2 6.1 30,131 1,022 1 7.5 4,952
8.1 360,184 49,126 6 70.2 8.1 32,325 1,096 0 7.5 6,637
10.1 425,718 32,734 6 70.2 10.1 34,225 949 1 7.5 8,089
12.1 491,252 32,734 5 70.2 12.1 34,225 0 0 7.5 0
14.1 589,554 49,102 7 70.2 14.1 34,225 0 0 7.5 0
16.1 655,088 32,734 5 70.2 16.1 34,225 0 0 7.5 0
18.1 720,622 32,734 6 70.2 18.1 34,225 0 0 7.5 0
receiver timed out
4.0 版本中的 AMQP 0.9.1
由于我们将 max_link_credit 设置为 2,000,我们允许发布者最多有 2,000 * 1.5 = 3,000 条未确认消息。
$ java -jar target/perf-test.jar \
--predeclared --exchange amq.default \
--routing-key my-quorum-queue --queue my-quorum-queue \
--flag persistent --flag mandatory \
--pmessages 1000000 --size 12 --confirm 3000 --qos 5000 --multi-ack-every 5000
id: test-085526-136, sending rate avg: 70067 msg/s
id: test-085526-136, receiving rate avg: 70067 msg/s
id: test-085526-136, consumer latency min/median/75th/95th/99th 8803/33127/40424/53407/62883 µs
id: test-085526-136, confirm latency min/median/75th/95th/99th 8551/30323/38317/52103/63131 µs
默认流控设置
$ java -jar target/perf-test.jar \
--predeclared --exchange amq.default \
--routing-key my-quorum-queue --queue my-quorum-queue \
--flag persistent --flag mandatory \
--pmessages 1000000 --size 12 --confirm 192 --qos 5000 --multi-ack-every 5000
id: test-084359-441, sending rate avg: 9931 msg/s
id: test-084359-441, receiving rate avg: 9931 msg/s
id: test-084359-441, consumer latency min/median/75th/95th/99th 7512/17054/26256/34249/38641 µs
id: test-084359-441, confirm latency min/median/75th/95th/99th 9432/16586/23918/32636/36858 µs
这些结果与 AMQP 1.0 (4.0 版本) 的默认流控设置的结果相似,因为这两个基准测试都受限于我的慢速磁盘。
摘要
流
本节测试 流。
我们声明一个名为 my-stream 的流。
deps/rabbitmq_management/bin/rabbitmqadmin declare queue \
name=my-stream queue_type=stream durable=true
(我们使用默认的 RabbitMQ 流控设置运行。)
我们希望接收方从流的开头开始消费。Quiver 不支持向 source 传递 filter 字段,以便我们可以指定 rabbitmq:stream-offset-spec 值 first。因此,对于此基准测试,默认情况下将流偏移量规范设置为 first 而不是 next,只需修补 RabbitMQ 即可。
git diff
diff --git a/deps/rabbit/src/rabbit_stream_queue.erl b/deps/rabbit/src/rabbit_stream_queue.erl
index e36ad708eb..acd193d76f 100644
--- a/deps/rabbit/src/rabbit_stream_queue.erl
+++ b/deps/rabbit/src/rabbit_stream_queue.erl
@@ -344,7 +344,7 @@ consume(Q, Spec, #stream_client{} = QState0)
{term(), non_neg_integer()}) ->
{ok, osiris:offset_spec()} | {error, term()}.
parse_offset_arg(undefined) ->
- {ok, next};
+ {ok, first};
parse_offset_arg({_, <<"first">>}) ->
{ok, first};
parse_offset_arg({_, <<"last">>}) ->
4.0 版本中的 AMQP 1.0
# quiver //host.docker.internal//queues/my-stream \
--durable --count 1m --duration 10m --body-size 12 --credit 5000
---------------------- Sender ----------------------- --------------------- Receiver ---------------------- --------
Time [s] Count [m] Rate [m/s] CPU [%] RSS [M] Time [s] Count [m] Rate [m/s] CPU [%] RSS [M] Lat [ms]
----------------------------------------------------- ----------------------------------------------------- --------
2.1 278,782 139,321 25 8.0 2.1 215,185 107,539 22 7.6 224
4.1 554,492 137,717 25 8.0 4.1 434,027 109,312 24 7.6 651
6.1 825,082 135,160 25 8.0 6.1 650,236 107,997 26 7.6 1,079
8.1 999,992 87,368 17 0.0 8.1 888,973 119,249 29 7.6 1,469
- - - - - 10.1 999,993 55,455 13 0.0 1,583
RESULTS
Count ............................................. 1,000,000 messages
Duration ................................................ 8.9 seconds
Sender rate ......................................... 136,705 messages/s
Receiver rate ....................................... 112,587 messages/s
End-to-end rate ..................................... 112,196 messages/s
Latencies by percentile:
0% ........ 7 ms 90.00% ..... 1553 ms
25% ...... 519 ms 99.00% ..... 1612 ms
50% ..... 1011 ms 99.90% ..... 1615 ms
100% ..... 1616 ms 99.99% ..... 1616 ms
可以很容易地观察到吞吐量大幅提高。
请注意,端到端延迟非常高,仅仅是因为发送方写入流的速度比 RabbitMQ 将消息分派给消费方(quiver 中的“接收方”)的速度快。
3.13 版本中的 AMQP 1.0
# quiver //host.docker.internal//amq/queue/my-stream \
--durable --count 1m --duration 10m --body-size 12 --credit 5000
---------------------- Sender ----------------------- --------------------- Receiver ---------------------- --------
Time [s] Count [m] Rate [m/s] CPU [%] RSS [M] Time [s] Count [m] Rate [m/s] CPU [%] RSS [M] Lat [ms]
----------------------------------------------------- ----------------------------------------------------- --------
2.1 196,350 98,077 12 70.1 2.1 4,094 2,045 0 7.7 195
4.1 392,956 98,205 13 138.5 4.1 4,094 0 0 7.7 0
6.1 524,026 65,470 10 196.5 6.1 4,094 0 0 7.7 0
8.1 655,096 65,470 11 259.4 8.1 4,094 0 0 7.7 0
10.1 786,166 65,470 10 307.5 10.1 4,094 0 0 7.7 0
receiver timed out
12.1 917,236 65,470 9 355.5 12.1 4,094 0 0 7.7 0
RabbitMQ 3.13 无法处理此工作负载,基准测试失败。
4.0 版本中的 AMQP 0.9.1
$ java -jar target/perf-test.jar \
--predeclared --exchange amq.default \
--routing-key my-stream --queue my-stream \
--flag persistent --flag mandatory \
--pmessages 1000000 --size 12 --confirm 192 --qos 5000 --multi-ack-every 5000
id: test-104223-225, sending rate avg: 88912 msg/s
id: test-104223-225, receiving rate avg: 88912 msg/s
id: test-104223-225, consumer latency min/median/75th/95th/99th 701/1340/1523/2500/4524 µs
id: test-104223-225, confirm latency min/median/75th/95th/99th 788/1983/2130/2437/2970 µs
由于流以 AMQP 1.0 格式存储消息,因此此工作负载要求 RabbitMQ 在 AMQP 0.9.1 和 AMQP 1.0 之间转换每条消息。这解释了为什么使用 AMQP 0.9.1 客户端时的流吞吐量低于使用 AMQP 1.0 客户端。
摘要
大量连接
本节比较了连接 40,000 个客户端(每个连接两个 AMQP 1.0 会话/AMQP 0.9.1 通道)的内存使用情况。
设置
make run-broker \
TEST_TMPDIR="$HOME/scratch/rabbit/test" \
RABBITMQ_CONFIG_FILE="$HOME/scratch/rabbit/rabbitmq.conf" \
PLUGINS="rabbitmq_amqp1_0" \
RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="+P 3000000 +S 6" \
ERL_MAX_PORTS=3000000
在以下 rabbitmq.conf 中,我们使用较小的缓冲区大小来更好地比较协议实现的内存使用情况。
tcp_listen_options.sndbuf = 2048
tcp_listen_options.recbuf = 2048
vm_memory_high_watermark.relative = 0.95
vm_memory_high_watermark_paging_ratio = 0.95
loopback_users = none
AMQP 1.0
package main
import (
"context"
"log"
"time"
"github.com/Azure/go-amqp"
)
func main() {
for i := 0; i < 40_000; i++ {
if i%1000 == 0 {
log.Printf("opened %d connections", i)
}
conn, err := amqp.Dial(
context.TODO(),
"amqp://",
&amqp.ConnOptions{SASLType: amqp.SASLTypeAnonymous()})
if err != nil {
log.Fatal("open connection:", err)
}
_, err = conn.NewSession(context.TODO(), nil)
if err != nil {
log.Fatal("begin session:", err)
}
_, err = conn.NewSession(context.TODO(), nil)
if err != nil {
log.Fatal("begin session:", err)
}
}
log.Println("opened all connections")
time.Sleep(5 * time.Hour)
}
AMQP 0.9.1
package main
import (
"log"
"time"
amqp "github.com/rabbitmq/amqp091-go"
)
func main() {
for i := 0; i < 40_000; i++ {
if i%1000 == 0 {
log.Printf("opened %d connections", i)
}
conn, err := amqp.Dial("amqp://guest:guest@localhost")
if err != nil {
log.Fatal("open connection:", err)
}
_, err = conn.Channel()
if err != nil {
log.Fatal("open channel:", err)
}
_, err = conn.Channel()
if err != nil {
log.Fatal("open channel:", err)
}
}
log.Println("opened all connections")
time.Sleep(5 * time.Hour)
}
下面的示例直接在节点上调用 erlang:memory/0,该函数返回每种内存类型的内存大小(以字节为单位)。
rabbitmq-diagnostics
要从正在运行的节点检索相同的信息,请使用 CLI 命令 rabbitmq-diagnostics,如下所示:
rabbitmq-diagnostics memory_breakdown
此命令可以使用不同的信息单位(例如 MiB、GiB)格式化数字,并支持使用 --formatter=json 进行 JSON 输出。
# pipes the output to `jq` for more readable formatting
rabbitmq-diagnostics memory_breakdown --formatter=json | jq
4.0 版本中的 AMQP 1.0
这是运行时报告的内存占用数字:
1> erlang:memory().
[{total,5330809208},
{processes,4788022888},
{processes_used,4787945960},
{system,542786320},
{atom,999681},
{atom_used,974364},
{binary,194810368},
{code,19328950},
{ets,94161808}]
2> erlang:system_info(process_count).
360312
3.13 版本中的 AMQP 1.0
供比较,此测试中运行时报告的内存占用数字为:
1> erlang:memory().
[{total,12066294144},
{processes,11156497904},
{processes_used,11156461208},
{system,909796240},
{atom,1089809},
{atom_used,1062780},
{binary,192784464},
{code,22068126},
{ets,318872128}]
2> erlang:system_info(process_count).
1480318
我们观察到 RabbitMQ 3.13 中 processes 的内存使用量为 11.1 GB,而 RabbitMQ 4.0 中仅为 4.8 GB(减少了约 56%)。如上一篇博文 关于 RabbitMQ 3.13 中 AMQP 1.0 的介绍中所述,RabbitMQ 3.13 中的 AMQP 1.0 实现资源消耗很大,因为该插件中的每个 AMQP 1.0 会话都包含一个 AMQP 0.9.1 客户端并维护 AMQP 0.9.1 状态。
4.0 版本中的 AMQP 0.9.1
1> erlang:memory().
[{total,5409763512},
{processes,4716150248},
{processes_used,4715945080},
{system,693613264},
{atom,991489},
{atom_used,962578},
{binary,187229040},
{code,19118766},
{ets,235605424}]
2> erlang:system_info(process_count).
600314
摘要
结论
本博文表明,RabbitMQ 4.0 中新的原生 AMQP 1.0 实现的性能是 RabbitMQ 3.13 中 AMQP 1.0 的多倍。
我们还观察到 AMQP 1.0 的性能可能优于 AMQP 0.9.1。但是,要进行公平的比较具有挑战性。本博文使用了用 C 语言编写的 AMQP 1.0 客户端和用 Java 语言编写的 AMQP 0.9.1 客户端。因此,我们不声明或承诺您将在 AMQP 1.0 工作负载中看到更高的吞吐量。RabbitMQ 中的 AMQP 0.9.1 实现性能良好,因为它已经稳定和优化了 15 年以上。
AMQP 1.0 可能优于 AMQP 0.9.1 的用例包括:
- 发送到或从流接收,因为流以 AMQP 1.0 格式编码消息(如本博文中所述)。
- 利用 RabbitMQ AMQP 1.0 Java 客户端的队列局部性。(此功能将单独介绍。)
- 当同一连接上的一个目标队列达到其限制时,发布到或从其他队列消耗(如 AMQP 1.0 流控博文 AMQP 1.0 流控中所述)。
