测试环境
硬件配置 | 4C 4G SSD |
---|---|
操作系统 | centeOS 6.5 |
MQ版本 | rocketmq-broker-4.2.0-incubating-SNAPSHOT (2017-08-23) |
测试程序运行机器:Macbook Pro i7 2.3GHz, 16G
单Broker场景
单broker同步发送(单发送进程),每条message大小:30bytes
NameServer与Broker分别在不同机器部署,broker采用异步持久化
topic设置:
perm: 6
JVM设置:
NameServer: -Xms1g -Xmx1g -Xmn512m
Broker: -Xms2g -Xmx2g -Xmn1g
发送条数 | 成功率 | 耗时(s) | 发送速率(条/秒) | 备注 |
---|---|---|---|---|
100000 | 100% | 74.265 | 1346.52 | 写queue数量:4 |
100000 | 100% | 75.347 | 1327.22 | 写queue数量:8 |
结论
成功率非常有保证,调整topic的queue数量并不能提升发送速率。broker的能力并没有完全被发挥出来,CPU非常闲。
单broker异步发送(单发送进程),每条message大小:30bytes
NameServer与Broker分别在不同机器部署,broker采用异步持久化
topic设置:
perm: 6
JVM设置:
NameServer: -Xms1g -Xmx1g -Xmn512m
Broker: -Xms2g -Xmx2g -Xmn1g
发送条数 | 成功率 | 耗时(s) | 发送速率(条/秒) | 备注 |
---|---|---|---|---|
1000000 | 100% | 33.420 | 29922.20 | 写queue数量:4,每发送37条休眠一毫秒,限制生产者速度不超过37000条/秒 |
1000000 | 96.6024% | 20.871 | 46285.46 | 写queue数量:4,发送端不限速 |
1000000 | 100% | 33.477 | 29871.25 | 写queue数量:8,每发送37条休眠一毫秒,限制生产者速度不超过37000条/秒 |
1000000 | 97.9327% | 22.961 | 48844.23 | 写queue数量:8,发送端不限速 |
结论
- 吞吐量较大时,会触发broker端的流控限制,会导致消息发送失败,出现异常:
Rocketmq:MQBrokerException: CODE: 2 DESC: [TIMEOUT_CLEAN_QUEUE]
。- 通过多次反复测试,发现在保证发送成功率
100%
的情况下,发送速率最大为29922.20条/秒
,测试过程中,测试程序最大上传网速达到15.9MB/s
。- 在成功率
100%
的情况下,吞吐量是同步发送的超20
倍。不限速(允许少量失败)的情况下,吞吐量是同步发送的超34
倍。- 在单发送进程场景下,增加topic的queue数量并不能提升生产速率。
发现的问题(或BUG)
测试发现
producer.shutdown()
时,并没有完全等待SendCallBack
执行完就退出,可能会导致有部分callback无法接收到。因此在在测试程序异步发送完成之后,还需要添加一个线程休眠,确保全部消息全部发送到broker。
单broker消费(单消费进程),每条message大小:30bytes
NameServer与Broker分别在不同机器部署
topic设置:
perm: 6
JVM设置:
NameServer: -Xms1g -Xmx1g -Xmn512m
Broker: -Xms2g -Xmx2g -Xmn1g
consumer设置:
consumeThreadMax: 64
pullBatchSize: 32
消费条数 | 成功率 | 耗时(s) | 消费速率(条/秒) | 备注 |
---|---|---|---|---|
3000000 | 100% | 21.353 | 140495.48 | 读queue数量:8 |
3000000 | 100% | 34.371 | 87282.88 | 读queue数量:4 |
结论
- RocketMQ的消息消费能力非常高,只要消费端的业务处理足够快。单broker的消费超过
7w条每秒
,基本上可以说满足大部分的实际业务场景。- 增加topic的queue数量,能明显提高消费速率。(前提是生产的消息要平均分布在各个queue)
- 从测试环境看,消费高峰每秒下载流量超过
31MB
,Broker的CPU会占用维持在50%
左右,消费过程中CPU的IOWait在某一瞬间会超过20%
。
单broker消费(双消费进程),每条message大小:30bytes
NameServer与Broker分别在不同机器部署
topic设置:
读队列数量:4
写队列数量:4
perm: 6
JVM设置:
NameServer: -Xms1g -Xmx1g -Xmn512m
Broker: -Xms2g -Xmx2g -Xmn1g
consumer设置:
consumeThreadMax: 64
pullBatchSize: 32
消费条数 | 成功率 | 耗时(s) | 消费速率(条/秒) | |
---|---|---|---|---|
消费进程 1 | 1000000 | 100% | 22.549 | 44347.86 |
消费进程2 | 1000000 | 100% | 21.360 | 46796.76 |
结论
增加消费者进程并不能提高整体的消费速度,因为消费者本身就是多线程的模式消费。但可以通过增加消费者进程来提升消费端高可用能力,避免消费端的单点故障。
多Master Broker场景
双Master Broker 同步发送,每条message大小:30bytes
三台主机,一台部署NameServer,另外两台各部署Broker master
topic设置:
perm: 6
JVM设置:
NameServer: -Xms1g -Xmx1g -Xmn512m
Broker: -Xms2g -Xmx2g -Xmn1g
发送条数 | 成功率 | 耗时(s) | 发送速率(条/秒) | 备注 |
---|---|---|---|---|
100000 | 100% | 66.845 | 1495.99 | 每个broker4个queue |
结论
同步发送速率双Master Borker与单broker基本在一个数量级 双Master Broker 异步发送(单发送进程),每条message大小:30bytes
三台主机,一台部署NameServer,另外两台各部署Broker master
topic设置:
perm: 6
JVM设置:
NameServer: -Xms1g -Xmx1g -Xmn512m
Broker: -Xms2g -Xmx2g -Xmn1g
Broker设置:
为提高成功率,将waitTimeMillsInSendQueue的默认值从200调整到1000
发送条数 | 成功率 | 耗时(s) | 发送速率(条/秒) | 备注 |
---|---|---|---|---|
1000000 | 100% | 20.862 | 47934.04 | 每个broker各4个queue, 每发送70条休眠1毫秒,确保每秒发送数量不超过7w条 |
1000000 | 100% | 20.616 | 48506.01 | 每个broker各8个queue, 每发送70条休眠1毫秒,确保每秒发送数量不超过7w条 |
1000000 | 99.7571% | 16.026 | 62247.03 | 每个broker各4个queue,生产者不限速 |
1000000 | 99.8807% | 17.108 | 58,382.45 | 每个broker各8个queue,生产者不限速 |
结论
- 在保证成功率100%的情况下,双master broker比单broker的发送速率明显提高,提升超
60%
。- 增加topic的queue数量,但发送进程并不能提高发送速率
双broker消费(单消费进程),每条message大小:30bytes
三台主机,一台部署NameServer,另外两台各部署Broker master
topic设置:
perm: 6
JVM设置:
NameServer: -Xms1g -Xmx1g -Xmn512m
Broker: -Xms2g -Xmx2g -Xmn1g
consumer设置:
consumeThreadMax: 64
pullBatchSize: 32
消费条数 | 成功率 | 耗时(s) | 消费速率(条/秒) | 备注 |
---|---|---|---|---|
2000000 | 100% | 11.170 | 179051.02 | 读queue数量:4 |
3000000 | 100% | 11.979 | 250438.26 | 读queue数量:8 |
结论
- 由于topic在每个broker上都有4个queue,发送的消息基本是均匀分配在两个broker的,因此在消费时能从两个broker分别进行消费,消费速率较单broker的消费提升了近1倍。
- 增大topic的queue数量,明显能提高消费速率。
双Master双Slave异步复制,异步发送,每条message大小:30bytes
五台主机,一台部署NameServer,两台分别部署broker-a-master、broker-a-slave,两台分别部署broker-b-master、broker-b-slave。
topic设置:
perm: 6
JVM设置:
NameServer: -Xms1g -Xmx1g -Xmn512m
Broker: -Xms2g -Xmx2g -Xmn1g
Broker设置:
master broker设置: brokerRole=ASYNC_MASTER
发送条数 | 成功率 | 耗时(s) | 发送速率(条/秒) | 备注 |
---|---|---|---|---|
100000 | 100% | 20.755 | 48181.16 | 每个broker各8个queue,每发送70条休眠1毫秒,确保每秒发送数量不超过7w条 |
结论
- Master与Slave采用异步复制时,基本不影响消息发送的吞吐量。
- 发送100w条消息到broker后(平均分配到broker-a与broker-b),关掉broker-b-master,启动消费者时,如果订阅组之前不存在,则不能从broker-b-slave上进行消费。如果订阅组存在,则能从broker-b-slave上进行消费,但当broker-b-master恢复之后,会重复消费broker-b-master上的消息。
发现的问题(或BUG)
在slave上进行消费时,消费的offset近保存到了slave上,当master恢复时,slave上的消费offset并没有被同步到master上,master上的offset还是最初在master上的消费位置,因此会导致master故障期间从slave上消费的消息会被重复消费。这应该不是RocketMQ的设计初衷,感觉像是个bug。
RocketMQ vs Kafka
- RocketMQ与Kafka一样,都没有JMS中定义的Queue的存在,只有Topic的存在。但他们都可以基于Topic来实现Queue的功能与特性。
- RocketMQ可以创建只有1个queue的topic,再结合Cluster的消费方式来实现JMS queue的功能与特性。
- Kafka则可以创建只有一个partition的topic来实现JMS Queue的功能与特性。
- RocketMQ中queue的概念可类比为Kafka中的partition,若要实现消息的强顺序消费,RocketMQ需要设置topic只有一个queue,Kafka则需要设置topic只有一个partition。
- 若业务规定只需保证同一订单编号的状态变更的顺序性,RocketMQ可以在发送时通过订单编号与MessageQueueSelector来实现同一编号的订单消息放置在topic的同一个queue中,Kafka则可以将订单编号作为消息的key来确保同一编号的订单消息放置在了同一个partition。