跳至主要内容

AMQP 1.0 基准测试

·阅读时长 17 分钟

这篇博文展示了 RabbitMQ 4.0 中的 原生 AMQP 1.0 与 RabbitMQ 3.13 中的 AMQP 1.0 相比,提供了显著的性能和可扩展性改进。

此外,这篇博文表明,在 RabbitMQ 4.0 中,AMQP 1.0 的性能可能略高于 AMQP 0.9.1。

设置

以下设置适用于本博文中的所有基准测试

  • 英特尔 NUC 11
  • 8 个 CPU 内核
  • 32 GB 内存
  • 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

摘要

Figure 1: Classic queue end-to-end message rate
图 1:经典队列端到端消息速率

仲裁队列

本节对 仲裁队列 进行基准测试。

我们声明一个名为 my-quorum-queue 的仲裁队列

deps/rabbitmq_management/bin/rabbitmqadmin declare queue \
name=my-quorum-queue queue_type=quorum durable=true

流量控制配置

为了获得最高的数据安全性,仲裁队列对所有 fsync Ra 命令执行以下操作,包括

  • 入队:发送方将消息入队
  • 结算:接收方接受消息
  • 信用:接收方补充链接信用

在仲裁队列向发布者确认收到消息之前,它会确保任何文件修改都已刷新到磁盘,即使 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 预写式日志)中调用了 1244 次 fsync。

使用默认流量控制设置的相同基准测试调用了 15493 次 fsync,导致吞吐量明显降低

# 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 会自动将多个 Raft 命令(操作)批处理到单个 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 设置为 2000,因此允许发布者中最多有 2000 * 1.5 = 3000 条未确认的消息。

$ 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

这些结果类似于 4.0 中的 AMQP 1.0 中的默认流量控制设置的结果,因为这两个基准测试都受到我缓慢磁盘的瓶颈。

摘要

Figure 2: Quorum queue end-to-end message rate
图 2:仲裁队列端到端消息速率

本节对 进行基准测试。

我们声明一个名为 my-stream 的流

deps/rabbitmq_management/bin/rabbitmqadmin declare queue \
name=my-stream queue_type=stream durable=true

(我们使用默认的 RabbitMQ 流量控制设置。)

我们希望接收器从流的开头开始消费。Quiver 不支持将 filter 字段传递给 ,我们可以在其中指定 rabbitmq:stream-offset-specfirst。因此,对于此基准测试,通过将流偏移量规范默认使用 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 客户端相比,流吞吐量较低。

摘要

Figure 3: Stream end-to-end message rate
图 3:流端到端消息速率

多个连接

本节比较了使用两个 AMQP 1.0 会话/每个连接的 AMQP 0.9.1 通道连接 40000 个客户端的内存使用情况。

设置
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://127.0.0.1",
&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

AMQP 1.0 在 4.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

AMQP 1.0 在 3.13 中

为了比较,此测试中运行时报告的内存占用数字为

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 的实现资源密集,因为插件中的每个 AMQP 1.0 会话都包含一个 AMQP 0.9.1 客户端,并维护 AMQP 0.9.1 状态。

AMQP 0.9.1 在 4.0 中

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

总结

Figure 4: Memory usage of 40,000 connections and 80,000 sessions / channels
图 4:40,000 个连接和 80,000 个会话/通道的内存使用情况

结论

这篇博文证明了 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 流量控制博文所述)。
© 2024 RabbitMQ. All rights reserved.