⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 http://www.iocoder.cn/Performance-Testing/RocketMQ-benchmark/ 「芋道源码」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

推荐阅读如下 RocketMQ 文章:

1. 概述

FROM 《消息中间件 Apache RocketMQ》

RocketMQ 是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。同时,广泛应用于多个领域,包括异步通信解耦、企业解决方案、金融支付、电信、电子商务、快递物流、广告营销、社交、即时通信、移动应用、手游、视频、物联网、车联网等。

具有以下特点:

  • 能够保证严格的消息顺序
  • 提供丰富的消息拉取模式
  • 高效的订阅者水平扩展能力
  • 实时的消息订阅机制
  • 亿级消息堆积能力
  • Metaq 3.0 版本改名,产品名称改为 RocketMQ

2013 年才开始使用 RocketMQ ,主要选型的原因是,Java 语言实现的高性能的消息队列中间件,可能比 RabbitMQ 自己会更容易把控。正好当时官方也提供了三个很牛逼的文档,让自己心里也更有底了:

2017 年的时候,因为想要进一步提(打)升(发)技(时)术(间),就学习了 RocketMQ 源码,并且写了第一套系列博客 《RocketMQ 源码解析》 。当然,一直以来比较遗憾的是,线上每天消息量都仅千万不到,没有机会体验 RocketMQ 大并发场景的使用。所以,我们今儿就来进行 RocketMQ 的性能基准测试,看看 RocketMQ 到底能跑多 666 。

2. 性能指标

《消息队列 RocketMQ 企业铂金版》 中,我们看到阿里云按照 TPS 的峰值进行定价,分别是(单位:月):

  • 5 千条/秒 :29480 元
  • 1 万条/秒 :34176 元
  • 2 万条/秒 :41220 元
  • 5 万条/秒 :52960 元
  • 10 万条/秒 :76440 元
  • 20 万条/秒 :170360 元
  • 30 万条/秒 :329232 元
  • 50 万元/秒 :571657 元
  • 80 万条/秒 :814081 元
  • 100 万条/秒 :1056505 元

艿艿:看到报价,瑟瑟发抖。

并且,Producer 发送一条消息,Consumer 消费一条消息,单独计算一条,也就是 2 条!

所以,本文我们,以 TPS 作为我们测试的重点。当然,我们也和阿里云相同的计算方式,按照消息大小基数为 1KB

3. 测试工具

目前可用于 RocketMQ 测试的工具,暂时没有。所幸,RocketMQ 的 benchmark 包下,提供了性能基准测试的工具。

事务消息,我们暂时不测试,所以我们需要使用的就是 Producer 和 Consumer 类。

4. 测试环境

  • 型号 :ecs.c5.xlarge

    艿艿:和我一样抠门(穷)的胖友,可以买竞价类型服务器,使用完后,做成镜像。等下次需要使用的时候,恢复一下。HOHO 。

  • 系统 :CentOS 7.6 64位

  • CPU :4 核

  • 内存 :8 GB

  • 磁盘 :100 GB ESSD 云盘,能够提供 6800 IOPS 。

  • Java :OpenJDK Runtime Environment (build 1.8.0_212-b04)

  • RocketMQ :4.5.1

我们买了两台阿里云 ECS ,用于搭建 RocketMQ 的一个主从集群。

我们会测试三轮,每一轮的目的分别是:

  • 1、Producer 在不同并发下的发送 TPS 。此时,我们会使用异步复制、异步刷盘的 RocketMQ 集群。
  • 2、Producer 在不同集群模式下的 RocketMQ 的发送 TPS 。此时,我们会使用相同的并发数。
  • 3、Consumer 的消费 TPS 。

注意,用于 RocketMQ 使用同一的 CommitLog 存储,所以 Topic 数量或是 Topic 的队列数,不影响 Producer 的发送 TPS 。

当然,更多的 Topic 的队列数,可以更多的 Consumer 消费,考虑到我们测试纸使用单个 Consumer ,所以还是默认队列大小为 4 ,不进行调整。

5. 搭建集群

本小节,我们来简述下,如何搭建一个 RocketMQ 集群。

1、编译 RocketMQ

可以参考 《Apache RocketMQ —— Quick Start》 文章。

作为一个菜鸡,还是希望 RocketMQ 官网,能够提供友好的文档,可以参考 Dubbo 官网

不过,无意中发现,原来 Github RocketMQ - /docs/cn 目录下,提供了中文文档,Amazing !

git clone https://github.com/apache/rocketmq
cd rocketmq
mvn -Prelease-all -DskipTests clean install -U

编译完成,在我们进入 distribution 目录下,就可以看到 RocketMQ 的发布包了。

$ cd distribution/target/rocketmq-4.5.1/rocketmq-4.5.1
$ ls

LICENSE NOTICE README.md benchmark bin conf lib

2、启动 Namesrv

在准备搭建 RocketMQ Master 主节点的机子上执行。

nohup sh bin/mqnamesrv &

启动完成后,查看日志。

tail -f ~/logs/rocketmqlogs/namesrv.log

2019-06-02 21:05:52 INFO main - The Name Server boot success. serializeType=JSON

3、启动 Broker Master 主节点

在 conf 目录下,提供了 RocketMQ 集群的配置:

  • 2m-2s-async :两主两从,异步复制,异步刷盘。
  • 2m-2s-sync :两主两从,同步复制,异步刷盘。

因为我们测试 RocketMQ 单集群,所以只需要使用上述配置的一主一从就可以了。不过,我们需要测试同步刷盘的情况,所以我们分别复制出 2m-2s-async-sync2m-2s-sync-sync 目录,修改成同步刷盘的配置。修改方式是,修改 broker-a.propertiesbroker-a-s.propertiesflushDiskType=SYNC_FLUSH 属性。

☺ OK,我们先使用 2m-2s-async 配置,启动一主一从 RocketMQ 集群,异步复制,异步刷盘。

因为我们的服务器是 4C8G ,内存相对小,所以我们修改下 runbroker.sh 脚本,将 Broker JVM 内存调小。如下:

JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -Xmn2g"

然后,我们来启动 RocketMQ Broker Master 主节点。

nohup sh bin/mqbroker -c conf/2m-2s-async/broker-a.properties  -n localhost:9876 &

  • 通过 -c 参数,配置读取的主 Broker 配置。
  • 通过 -n 参数,设置 RocketMQ Namesrv 地址。

启动完成后,查看日志。

tail -f ~/logs/rocketmqlogs/broker.log

2019-06-02 21:45:45 INFO main - The broker[broker-a, 172.19.83.161:10911] boot success. serializeType=JSON and name server is localhost:9876

4、启动 Broker Slave 子节点

在第二台阿里云 ECS 上,启动 Broker Slave 子节点。

nohup sh bin/mqbroker -c conf/2m-2s-async/broker-a-s.properties  -n 172.19.83.161:9876 &

  • 通过 -c 参数,配置读取的从 Broker 配置。
  • 通过 -n 参数,设置 RocketMQ Namesrv 地址。这里,一定要改成自己的 Namesrv 地址噢。

启动完成后,查看日志。

2019-06-02 22:01:46 INFO main - The broker[broker-a, 172.19.83.162:10911] boot success. serializeType=JSON and name server is 172.19.83.161:9876
2019-06-02 22:01:49 INFO BrokerControllerScheduledThread1 - Update slave topic config from master, 172.19.83.161:10911
2019-06-02 22:01:49 INFO BrokerControllerScheduledThread1 - Update slave consumer offset from master, 172.19.83.161:10911

5、测试消息发送

在第一台阿里云 ECS 上,测试消息发送。

export NAMESRV_ADDR=localhost:9876
sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer

如果发送成功,我们会看到大量成功的发送日志。

BE2, messageQueue=MessageQueue [topic=TopicTest, brokerName=broker-a, queueId=0], queueOffset=249]
SendResult [sendStatus=SEND_OK, msgId=AC1353A112006F94FA3E09EEA17003E5, offsetMsgId=AC1353A100002A9F000000000002BC96, messageQueue=MessageQueue [topic=TopicTest, brokerName=broker-a, queueId=1], queueOffset=249]
SendResult [sendStatus=SEND_OK, msgId=AC1353A112006F94FA3E09EEA17103E6, offsetMsgId=AC1353A100002A9F000000000002BD4A, messageQueue=MessageQueue [topic=TopicTest, brokerName=broker-a, queueId=2], queueOffset=249]
SendResult [sendStatus=SEND_OK, msgId=AC1353A112006F94FA3E09EEA17103E7, offsetMsgId=AC1353A100002A9F000000000002BDFE, messageQueue=MessageQueue [topic=TopicTest, brokerName=broker-a, queueId=3], queueOffset=249]

至此,我们的 RocketMQ 一主一从集群,就成功的搭建完成。下面,我们开始正片流程,开始基准测试流程。

6. 第一轮

这一轮,我们来测试 Producer 在不同并发下的发送 TPS 。此时,我们会使用异步复制、异步刷盘的 RocketMQ 集群。对应的 RocketMQ Broker 配置文件是,2m-2s-async 文件。

这里,我们将测试的并发数,分别是 1、8、16、32、64、128 。

在 benchmark 目录下,已经提供了对 Producer.javaConsumer.java 的封装,可以直接使用。如下:

$ ls
LICENSE NOTICE README.md benchmark bin conf hs_err_pid4469.log lib nohup.out

$ cd benchmark
$ ls
consumer.sh producer.sh runclass.sh tproducer.sh

要注意,benchmark 下的 shell 脚本,需要设置正确 JAVA_HOME 地址。😈 例如说,我是使用 yum 安装的 OpenJDK ,如下:

export JAVA_HOME=/usr/lib/jvm/java/

6.1 并发量为 1

sh producer.sh --w=1 --s=1024

  • 通过 --w 参数,设置并发线程数。
  • 通过 --s 参数,设置 Topic 消息大小。

执行结果如下:

Send TPS: 3770 Max RT: 198 Average RT:   0.259 Send Failed: 0 Response Failed: 0
Send TPS: 3803 Max RT: 198 Average RT: 0.257 Send Failed: 0 Response Failed: 0
Send TPS: 3817 Max RT: 198 Average RT: 0.257 Send Failed: 0 Response Failed: 0
Send TPS: 3819 Max RT: 198 Average RT: 0.256 Send Failed: 0 Response Failed: 0
Send TPS: 3846 Max RT: 198 Average RT: 0.255 Send Failed: 0 Response Failed: 0
Send TPS: 3813 Max RT: 198 Average RT: 0.257 Send Failed: 0 Response Failed: 0
Send TPS: 3784 Max RT: 198 Average RT: 0.259 Send Failed: 0 Response Failed: 0
Send TPS: 3833 Max RT: 198 Average RT: 0.255 Send Failed: 0 Response Failed: 0
Send TPS: 3797 Max RT: 198 Average RT: 0.257 Send Failed: 0 Response Failed: 0
Send TPS: 3828 Max RT: 198 Average RT: 0.256 Send Failed: 0 Response Failed: 0
Send TPS: 3848 Max RT: 198 Average RT: 0.255 Send Failed: 0 Response Failed: 0
Send TPS: 3836 Max RT: 198 Average RT: 0.255 Send Failed: 0 Response Failed: 0
Send TPS: 3819 Max RT: 198 Average RT: 0.256 Send Failed: 0 Response Failed: 0
Send TPS: 3841 Max RT: 198 Average RT: 0.254 Send Failed: 0 Response Failed: 0
Send TPS: 3821 Max RT: 198 Average RT: 0.256 Send Failed: 0 Response Failed: 0
Send TPS: 3813 Max RT: 198 Average RT: 0.257 Send Failed: 0 Response Failed: 0
Send TPS: 3813 Max RT: 198 Average RT: 0.257 Send Failed: 0 Response Failed: 0
Send TPS: 3818 Max RT: 198 Average RT: 0.256 Send Failed: 0 Response Failed: 0
Send TPS: 3816 Max RT: 198 Average RT: 0.256 Send Failed: 0 Response Failed: 0

  • TPS :3800 左右。
  • Average RT :0.256ms 左右。
  • Max RT :198ms 左右。

因为 producer.sh 是后台执行的,所以每次测试完,需要 kill 掉。例如:

$ ¥ps -ef | grep Producer
root 7197 1 0 10:31 pts/0 00:00:00 sh ./runclass.sh -Dorg.apache.rocketmq.client.sendSmartMsg=true org.apache.rocketmq.example.benchmark.Producer --w=8 --s=1024

$ kill -9 7197 # 直接强制 kill 哈。

6.2 并发量为 8

sh producer.sh --w=8 --s=1024

执行结果如下:

Send TPS: 18065 Max RT: 984 Average RT:   0.438 Send Failed: 0 Response Failed: 7
Send TPS: 17057 Max RT: 984 Average RT: 0.444 Send Failed: 0 Response Failed: 14
Send TPS: 15182 Max RT: 984 Average RT: 0.432 Send Failed: 0 Response Failed: 14
Send TPS: 18025 Max RT: 984 Average RT: 0.439 Send Failed: 0 Response Failed: 14
Send TPS: 18134 Max RT: 984 Average RT: 0.437 Send Failed: 0 Response Failed: 14

  • TPS :18000 左右。
  • Average RT :0.439ms 左右。
  • Max RT :984ms 左右。
  • 存在极少量发送失败的消息。

6.3 并发量为 16

sh producer.sh --w=16 --s=1024

执行结果如下:

Send TPS: 22511 Max RT: 705 Average RT:   0.707 Send Failed: 0 Response Failed: 30
Send TPS: 22615 Max RT: 705 Average RT: 0.703 Send Failed: 0 Response Failed: 30
Send TPS: 22078 Max RT: 705 Average RT: 0.721 Send Failed: 0 Response Failed: 30
Send TPS: 21962 Max RT: 705 Average RT: 0.724 Send Failed: 0 Response Failed: 30
Send TPS: 22067 Max RT: 705 Average RT: 0.721 Send Failed: 0 Response Failed: 30
Send TPS: 21932 Max RT: 705 Average RT: 0.726 Send Failed: 0 Response Failed: 30
Send TPS: 22459 Max RT: 705 Average RT: 0.709 Send Failed: 0 Response Failed: 30
Send TPS: 15611 Max RT: 705 Average RT: 0.678 Send Failed: 0 Response Failed: 45
Send TPS: 22235 Max RT: 705 Average RT: 0.716 Send Failed: 0 Response Failed: 45
Send TPS: 22391 Max RT: 705 Average RT: 0.711 Send Failed: 0 Response Failed: 45
Send TPS: 21600 Max RT: 705 Average RT: 0.737 Send Failed: 0 Response Failed: 45
Send TPS: 22233 Max RT: 705 Average RT: 0.715 Send Failed: 0 Response Failed: 45

  • TPS :22000 左右。
  • Average RT :0.715ms 左右。
  • Max RT :705ms 左右。
  • 存在极少量发送失败的消息。

6.4 并发量为 32

sh producer.sh --w=32 --s=1024

执行结果如下:

Send TPS: 17980 Max RT: 1102 Average RT:   1.159 Send Failed: 0 Response Failed: 93
Send TPS: 26759 Max RT: 1102 Average RT: 1.189 Send Failed: 0 Response Failed: 93
Send TPS: 22599 Max RT: 1102 Average RT: 1.183 Send Failed: 0 Response Failed: 124
Send TPS: 20627 Max RT: 1102 Average RT: 1.168 Send Failed: 0 Response Failed: 155
Send TPS: 24675 Max RT: 1102 Average RT: 1.196 Send Failed: 0 Response Failed: 155
Send TPS: 26706 Max RT: 1102 Average RT: 1.192 Send Failed: 0 Response Failed: 155
Send TPS: 18342 Max RT: 1102 Average RT: 1.132 Send Failed: 0 Response Failed: 186
Send TPS: 26663 Max RT: 1102 Average RT: 1.194 Send Failed: 0 Response Failed: 186
Send TPS: 19870 Max RT: 1102 Average RT: 1.166 Send Failed: 0 Response Failed: 217
Send TPS: 26842 Max RT: 1102 Average RT: 1.186 Send Failed: 0 Response Failed: 217
Send TPS: 27095 Max RT: 1102 Average RT: 1.175 Send Failed: 0 Response Failed: 217
Send TPS: 19093 Max RT: 1102 Average RT: 1.150 Send Failed: 0 Response Failed: 248
Send TPS: 26416 Max RT: 1102 Average RT: 1.205 Send Failed: 0 Response Failed: 248
Send TPS: 18032 Max RT: 1102 Average RT: 1.156 Send Failed: 0 Response Failed: 279
Send TPS: 26771 Max RT: 1102 Average RT: 1.189 Send Failed: 0 Response Failed: 279
Send TPS: 26543 Max RT: 1102 Average RT: 1.199 Send Failed: 0 Response Failed: 279
Send TPS: 20932 Max RT: 1102 Average RT: 1.148 Send Failed: 0 Response Failed: 310
Send TPS: 24804 Max RT: 1102 Average RT: 1.195 Send Failed: 0 Response Failed: 341
Send TPS: 22384 Max RT: 1102 Average RT: 1.177 Send Failed: 0 Response Failed: 341
Send TPS: 26247 Max RT: 1102 Average RT: 1.213 Send Failed: 0 Response Failed: 341

  • TPS :26000 左右。波动较大。
  • Average RT :1.213ms 左右。
  • Max RT :1102ms 左右。
  • 存在极少量发送失败的消息。

6.5 并发量为 64

sh producer.sh --w=64 --s=1024

执行结果如下:

Send TPS: 25256 Max RT: 579 Average RT:   2.527 Send Failed: 0 Response Failed: 0
Send TPS: 17181 Max RT: 832 Average RT: 2.157 Send Failed: 0 Response Failed: 63
Send TPS: 29850 Max RT: 832 Average RT: 2.137 Send Failed: 0 Response Failed: 63
Send TPS: 29571 Max RT: 832 Average RT: 2.157 Send Failed: 0 Response Failed: 63
Send TPS: 29734 Max RT: 832 Average RT: 2.146 Send Failed: 0 Response Failed: 63
Send TPS: 20329 Max RT: 1108 Average RT: 2.036 Send Failed: 0 Response Failed: 126
Send TPS: 30445 Max RT: 1108 Average RT: 2.096 Send Failed: 0 Response Failed: 126
Send TPS: 20297 Max RT: 1108 Average RT: 2.038 Send Failed: 0 Response Failed: 189
Send TPS: 30163 Max RT: 1108 Average RT: 2.115 Send Failed: 0 Response Failed: 189

  • TPS :29000 左右。波动较大。
  • Average RT :2.115ms 左右。
  • Max RT :1108ms 左右。
  • 存在极少量发送失败的消息。

6.6 并发量为 128

sh producer.sh --w=128 --s=1024

执行结果如下:

Send TPS: 22229 Max RT: 884 Average RT:   3.651 Send Failed: 0 Response Failed: 254
Send TPS: 33189 Max RT: 884 Average RT: 3.847 Send Failed: 0 Response Failed: 254
Send TPS: 32674 Max RT: 884 Average RT: 3.906 Send Failed: 0 Response Failed: 254
Send TPS: 20664 Max RT: 884 Average RT: 3.977 Send Failed: 0 Response Failed: 381
Send TPS: 32697 Max RT: 884 Average RT: 3.905 Send Failed: 0 Response Failed: 381
Send TPS: 22260 Max RT: 884 Average RT: 3.704 Send Failed: 0 Response Failed: 508
Send TPS: 23163 Max RT: 884 Average RT: 3.822 Send Failed: 0 Response Failed: 635
Send TPS: 22214 Max RT: 884 Average RT: 3.717 Send Failed: 0 Response Failed: 762
Send TPS: 33026 Max RT: 884 Average RT: 3.878 Send Failed: 0 Response Failed: 762
Send TPS: 32407 Max RT: 884 Average RT: 3.939 Send Failed: 0 Response Failed: 762
Send TPS: 22484 Max RT: 884 Average RT: 3.670 Send Failed: 0 Response Failed: 889
Send TPS: 24857 Max RT: 884 Average RT: 3.729 Send Failed: 0 Response Failed: 1016
Send TPS: 22179 Max RT: 884 Average RT: 3.718 Send Failed: 0 Response Failed: 1143
Send TPS: 22307 Max RT: 884 Average RT: 3.700 Send Failed: 0 Response Failed: 1270
Send TPS: 12191 Max RT: 884 Average RT: 3.232 Send Failed: 0 Response Failed: 1524
Send TPS: 32359 Max RT: 884 Average RT: 3.781 Send Failed: 0 Response Failed: 1539
Send TPS: 23205 Max RT: 884 Average RT: 3.720 Send Failed: 0 Response Failed: 1666
Send TPS: 32798 Max RT: 884 Average RT: 3.892 Send Failed: 0 Response Failed: 1666
Send TPS: 21936 Max RT: 884 Average RT: 3.762 Send Failed: 0 Response Failed: 1793
Send TPS: 33008 Max RT: 884 Average RT: 3.868 Send Failed: 0 Response Failed: 1793
Send TPS: 22432 Max RT: 884 Average RT: 3.674 Send Failed: 0 Response Failed: 1920
Send TPS: 25763 Max RT: 884 Average RT: 3.835 Send Failed: 0 Response Failed: 2047

  • TPS :波动比较大,很难统计。
  • Average RT :3.822ms 左右。
  • Max RT :884ms 左右。
  • 存在极少量发送失败的消息。

7. 第二轮

通过第一轮的测试,考虑到测试结果的稳定性,我们选用 Producer 并发量为 20 的大小,进行测试。

7.1 异步复制 + 异步刷盘

使用配置文件 2m-2s-async 目录。

sh producer.sh --w=16 --s=1024

执行结果如下:

Send TPS: 22511 Max RT: 705 Average RT:   0.707 Send Failed: 0 Response Failed: 30
Send TPS: 22615 Max RT: 705 Average RT: 0.703 Send Failed: 0 Response Failed: 30
Send TPS: 22078 Max RT: 705 Average RT: 0.721 Send Failed: 0 Response Failed: 30
Send TPS: 21962 Max RT: 705 Average RT: 0.724 Send Failed: 0 Response Failed: 30
Send TPS: 22067 Max RT: 705 Average RT: 0.721 Send Failed: 0 Response Failed: 30
Send TPS: 21932 Max RT: 705 Average RT: 0.726 Send Failed: 0 Response Failed: 30
Send TPS: 22459 Max RT: 705 Average RT: 0.709 Send Failed: 0 Response Failed: 30
Send TPS: 15611 Max RT: 705 Average RT: 0.678 Send Failed: 0 Response Failed: 45
Send TPS: 22235 Max RT: 705 Average RT: 0.716 Send Failed: 0 Response Failed: 45
Send TPS: 22391 Max RT: 705 Average RT: 0.711 Send Failed: 0 Response Failed: 45
Send TPS: 21600 Max RT: 705 Average RT: 0.737 Send Failed: 0 Response Failed: 45
Send TPS: 22233 Max RT: 705 Average RT: 0.715 Send Failed: 0 Response Failed: 45

  • TPS :22000 左右。
  • Average RT :0.715ms 左右。
  • Max RT :705ms 左右。
  • 存在极少量发送失败的消息。

7.2 同步复制 + 异步刷盘

使用配置文件 2m-2s-sync 目录。

  • 主 Broker :nohup sh bin/mqbroker -c conf/2m-2s-sync/broker-a.properties -n localhost:9876 &
  • 从 Broker :nohup sh bin/mqbroker -c conf/2m-2s-sync/broker-a-s.properties -n 172.19.83.161:9876 &

另外,参考 《官方文档 —— 运维管理》 的 「3.5 性能调优问题」中,描述 sendMessageThreadPoolNums 参数,对同步复制和同步刷盘,是有性能影响的,所以我们修改成 sendMessageThreadPoolNums = 16 + Runtime.getRuntime().availableProcessors() * 4 = 16 + 4 * 4 = 32 。这个公式,可以在 BrokerConfig.sendMessageThreadPoolNums 类中看到。

sh producer.sh --w=16 --s=1024

执行结果如下:

Send TPS: 7678 Max RT: 312 Average RT:   2.078 Send Failed: 0 Response Failed: 0
Send TPS: 6468 Max RT: 312 Average RT: 2.470 Send Failed: 0 Response Failed: 0
Send TPS: 3552 Max RT: 1942 Average RT: 4.229 Send Failed: 0 Response Failed: 0
Send TPS: 6014 Max RT: 2187 Average RT: 3.105 Send Failed: 0 Response Failed: 0
Send TPS: 7261 Max RT: 2187 Average RT: 2.200 Send Failed: 0 Response Failed: 0
Send TPS: 6873 Max RT: 2187 Average RT: 2.320 Send Failed: 0 Response Failed: 0
Send TPS: 7070 Max RT: 2187 Average RT: 2.267 Send Failed: 0 Response Failed: 0
Send TPS: 7118 Max RT: 2187 Average RT: 2.245 Send Failed: 0 Response Failed: 0
Send TPS: 5528 Max RT: 2187 Average RT: 2.889 Send Failed: 0 Response Failed: 0
Send TPS: 6819 Max RT: 2187 Average RT: 2.341 Send Failed: 0 Response Failed: 0
Send TPS: 6734 Max RT: 2187 Average RT: 2.373 Send Failed: 0 Response Failed: 0
Send TPS: 7058 Max RT: 2187 Average RT: 2.260 Send Failed: 0 Response Failed: 0
Send TPS: 6237 Max RT: 2187 Average RT: 2.560 Send Failed: 0 Response Failed: 0
Send TPS: 6708 Max RT: 2187 Average RT: 2.380 Send Failed: 0 Response Failed: 0
Send TPS: 6665 Max RT: 2187 Average RT: 2.388 Send Failed: 0 Response Failed: 0
Send TPS: 7202 Max RT: 2187 Average RT: 2.237 Send Failed: 0 Response Failed: 0
Send TPS: 7486 Max RT: 2187 Average RT: 2.129 Send Failed: 0 Response Failed: 0

  • TPS :7000 左右。
  • Average RT :2.129ms 左右。
  • Max RT :2187ms 左右。

相比“异步复制 + 异步刷盘”来说,性能有比较大的下滑。不过在看 《官方文档 —— 运维管理》 的「1.4 多Master多Slave模式-同步双写」中,描述说,“性能比异步复制模式略低(大约低10%左右)”。这点,让我有点懵逼。感兴趣的胖友,可以也测试下,分享下结果。

7.3 异步复制 + 同步刷盘

使用配置文件 2m-2s-async-sync 目录。

  • 主 Broker :nohup sh bin/mqbroker -c conf/2m-2s-async-sync/broker-a.properties -n localhost:9876 &
  • 从 Broker :nohup sh bin/mqbroker -c conf/2m-2s-async-sync/broker-a-s.properties -n 172.19.83.161:9876 &

sh producer.sh --w=16 --s=1024

执行结果如下:

Send TPS: 2645 Max RT: 267 Average RT:   6.032 Send Failed: 0 Response Failed: 0
Send TPS: 2513 Max RT: 267 Average RT: 6.355 Send Failed: 0 Response Failed: 0
Send TPS: 2527 Max RT: 267 Average RT: 6.318 Send Failed: 0 Response Failed: 0
Send TPS: 2607 Max RT: 267 Average RT: 6.113 Send Failed: 0 Response Failed: 0
Send TPS: 2790 Max RT: 267 Average RT: 5.731 Send Failed: 0 Response Failed: 0
Send TPS: 2558 Max RT: 267 Average RT: 6.257 Send Failed: 0 Response Failed: 0
Send TPS: 2681 Max RT: 267 Average RT: 5.959 Send Failed: 0 Response Failed: 0
Send TPS: 2829 Max RT: 267 Average RT: 5.648 Send Failed: 0 Response Failed: 0

  • TPS :2600 左右。
  • Average RT :5.648ms 左右。
  • Max RT :267ms 左右。

7.4 同步复制 + 同步刷盘

使用配置文件 2m-2s-sync-sync 目录。

  • 主 Broker :nohup sh bin/mqbroker -c conf/2m-2s-sync-sync/broker-a.properties -n localhost:9876 &
  • 从 Broker :nohup sh bin/mqbroker -c conf/2m-2s-sync-sync/broker-a-s.properties -n 172.19.83.161:9876 &

sh producer.sh --w=16 --s=1024

执行结果如下:

Send TPS: 3567 Max RT: 308 Average RT:   4.481 Send Failed: 0 Response Failed: 0
Send TPS: 3391 Max RT: 308 Average RT: 4.705 Send Failed: 0 Response Failed: 0
Send TPS: 3392 Max RT: 308 Average RT: 4.709 Send Failed: 0 Response Failed: 0
Send TPS: 3147 Max RT: 308 Average RT: 5.072 Send Failed: 0 Response Failed: 0
Send TPS: 3276 Max RT: 308 Average RT: 4.886 Send Failed: 0 Response Failed: 0

  • TPS :3200 左右。
  • Average RT :5.072ms 左右。
  • Max RT :308ms 左右。

7.5 小结

从性能上来看,异步复制 + 异步刷盘的方式,性能是最优秀的,甩其它方式好几条街。所以,生产上,最多使用的也是这种方式。另外,异步刷盘,可以配置 transientStorePoolEnable = true ,进一步提升性能。

当然,比较奇怪但是,异步复制 + 同步刷盘 TPS 低于同步复制 + 同步刷盘,有点神奇?!具体的原因,还没去深究。

另外,RocketMQ 提供了基于 Raft 协议的 CommitLog 存储库 dledger 的方式,暂时并未去测试。

8. 第三轮

因为 RocketMQ benchmark 提供的 Consumer 测试,每次都启动一个新的消费集群,并且从 CONSUME_FROM_LAST_OFFSET 进行开始测试消费。所以,我们需要启动一个 Producer 不断发新消息,提供给消费者消费。

本轮,我们将启动异步复制 + 异步刷盘 RocketMQ 集群,并且使用 Producer 按照并发量为 16进行发送消息。

艿艿:此处,我们假装胖友已经启动好 Broker 和 Producer 。

sh consumer.sh

执行结果如下:

Consume TPS: 13955 Average(B2C) RT:   3.693 Average(S2C) RT:   3.059 MAX(B2C) RT: 8602 MAX(S2C) RT: 8602
Consume TPS: 14920 Average(B2C) RT: 2.227 Average(S2C) RT: 1.643 MAX(B2C) RT: 8602 MAX(S2C) RT: 8602
Consume TPS: 15070 Average(B2C) RT: 2.223 Average(S2C) RT: 1.642 MAX(B2C) RT: 8602 MAX(S2C) RT: 8602
Consume TPS: 15142 Average(B2C) RT: 2.371 Average(S2C) RT: 1.806 MAX(B2C) RT: 8602 MAX(S2C) RT: 8602
Consume TPS: 10703 Average(B2C) RT: 2.326 Average(S2C) RT: 1.792 MAX(B2C) RT: 8602 MAX(S2C) RT: 8602

  • 消费的 TPS 是 15000 左右。此时 Producer TPS 如下:

    Send TPS: 14901 Max RT: 2004 Average RT:   1.068 Send Failed: 0 Response Failed: 15
    Send TPS: 14982 Max RT: 2004 Average RT: 1.062 Send Failed: 0 Response Failed: 15
    Send TPS: 15123 Max RT: 2004 Average RT: 1.052 Send Failed: 0 Response Failed: 15
    Send TPS: 11460 Max RT: 2004 Average RT: 0.989 Send Failed: 0 Response Failed: 30
    Send TPS: 15466 Max RT: 2004 Average RT: 1.029 Send Failed: 0 Response Failed: 30
    Send TPS: 15110 Max RT: 2004 Average RT: 1.053 Send Failed: 0 Response Failed: 30
    Send TPS: 15132 Max RT: 2004 Average RT: 1.052 Send Failed: 0 Response Failed: 30
    Send TPS: 15265 Max RT: 2004 Average RT: 1.042 Send Failed: 0 Response Failed: 30
    Send TPS: 11945 Max RT: 2004 Average RT: 1.033 Send Failed: 0 Response Failed: 45
    Send TPS: 15027 Max RT: 2004 Average RT: 1.052 Send Failed: 0 Response Failed: 45
    Send TPS: 15233 Max RT: 2004 Average RT: 1.045 Send Failed: 0 Response Failed: 45
    Send TPS: 15237 Max RT: 2004 Average RT: 1.044 Send Failed: 0 Response Failed: 45
    Send TPS: 15182 Max RT: 2004 Average RT: 1.047 Send Failed: 0 Response Failed: 45

    • 发送的 Producer 的 TPS 也是 15000 左右。
  • 因为测试的 Consumer ,是直接启动在 Broker 主节点,而测试的 Producer 也是直接启动在 Broker 主节点。所以测试出来的 TPS 并没有跑到 22000+ 。当然,从这个数据,我们也可以看出,Consumer 可以追上 Producer 的发送速度。

😈 Consumer 测试的比较偷懒,感兴趣的胖友,可以把 Consumer 启动在 Broker 从节点,进行基准测试。

666. 彩蛋

从本文的性能测试可以看出,如果团队有能力或者愿意去运维 RocketMQ 集群,还是能节约非常多的服务器成本。这也是为什么很多大体量的团队,都是自建 RocketMQ 集群的原因。

T T 因为偷懒,所以没有贴出 CPU、内存、磁盘等监控情况。勤快的胖友,自己在测试的时候,观察下服务器的状况。

因为本文可能并未覆盖很多测试场景,胖友可以看看其他文章,例如:

文章目录
  1. 1. 1. 概述
  2. 2. 2. 性能指标
  3. 3. 3. 测试工具
  4. 4. 4. 测试环境
  5. 5. 5. 搭建集群
  6. 6. 6. 第一轮
    1. 6.1. 6.1 并发量为 1
    2. 6.2. 6.2 并发量为 8
    3. 6.3. 6.3 并发量为 16
    4. 6.4. 6.4 并发量为 32
    5. 6.5. 6.5 并发量为 64
    6. 6.6. 6.6 并发量为 128
  7. 7. 7. 第二轮
    1. 7.1. 7.1 异步复制 + 异步刷盘
    2. 7.2. 7.2 同步复制 + 异步刷盘
    3. 7.3. 7.3 异步复制 + 同步刷盘
    4. 7.4. 7.4 同步复制 + 同步刷盘
    5. 7.5. 7.5 小结
  8. 8. 8. 第三轮
  9. 9. 666. 彩蛋