1.环境参考
benchmark环境搭建:参考单机快速搭建单broker环境
被压测环境:rocketmq的dledger集群
2.源码位置
https://github.com/apache/rocketmq/tree/master/example/src/main/java/org/apache/rocketmq/example/benchmark
3.工具清单
consumer.sh:消息消费的benchmark工具
producer.sh: 消息生产benchmark工具(同步非批处理模式)
3.1 producer.sh
3.1.1 帮助
sh producer.sh -h
usage: benchmarkProducer [-h] [-k
-h,--help Print help
-k,--keyEnable
-n,--namesrvAddr
-s,--messageSize
-t,--topic
-w,--threadCount
3.1.2 源码重要片段
//默认生产组为:benchmark_producer final DefaultMQProducer producer = new DefaultMQProducer("benchmark_producer"); //如果keyEnable为True,则会以时间戳作为message的key if (keyEnable) { msg.setKeys(String.valueOf(beginTimestamp / 1000)); } //设置producer用于发送消息的线程池大小,-w的值 final ExecutorService sendThreadPool = Executors.newFixedThreadPool(threadCount);
3.1.3 例子
指定nameserver进行生产消息压测
sh producer.sh -n xxx.xxx.xxx.xxx:9876
SendTPS:生产消息的TPS
Max RT:最大响应时间(毫秒)
Average RT:平均响应时间(毫秒)
Send Failed:发送失败的总请求数
Response Failed:返回失败的总响应数
这里刚开始有发生失败的原因是由于producer刚启动,短期内对broker造成了压力。在实际使用producer的时候,应该对发送失败的情况进行重新消息重发。
可以看到控制台里Produce Message TPS为3000多,其中slave是从master同步消息的TPS(备份master的消息数据),master才是实际接收的生产消息TPS。
3.2 consumer.sh
3.2.1 帮助
sh consumer.sh -h
usage: benchmarkConsumer [-e
-e,--expression
-f,--filterType
-g,--group
-h,--help Print help
-n,--namesrvAddr
-p,--group prefix enable
-r,--fail rate
-t,--topic
3.2.2 源码重要片段
#根据指定的消费group生成消费者
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(group);
#指定nameserver地址
if (commandLine.hasOption('n')) {
String ns = commandLine.getOptionValue('n');
consumer.setNamesrvAddr(ns);
}
#如果没有指定isSuffixEnable,即-p指定的数值,则会给消费组加上后缀
if (Boolean.parseBoolean(isSuffixEnable)) {
group = groupPrefix + "_" + (System.currentTimeMillis() % 100);
}
#指定topic的消息过滤器,只消费符合条件的消息
#SQL92语法
#TAG语言
if (filterType == null || expression == null) {
consumer.subscribe(topic, "*");
} else {
if (ExpressionType.TAG.equals(filterType)) {
String expr = MixAll.file2String(expression);
System.out.printf("Expression: %s%n", expr);
consumer.subscribe(topic, MessageSelector.byTag(expr));
} else if (ExpressionType.SQL92.equals(filterType)) {
String expr = MixAll.file2String(expression);
System.out.printf("Expression: %s%n", expr);
consumer.subscribe(topic, MessageSelector.bySql(expr));
} else {
throw new IllegalArgumentException("Not support filter type! " + filterType);
}
}
#如果当前消费比例小于failRate,会稍后进行重试消费,否则直接跳过
if (ThreadLocalRandom.current().nextDouble() < failRate) {
statsBenchmarkConsumer.getFailCount().incrementAndGet();
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
} else {
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
3.2.3 例子
#从BenchmarkTest消费消息,这里会自动给消费组:test2加上一个后缀
sh consumer.sh -t BenchmarkTest -n nameserver:9876 -g test2
TPS: 消费的TPS
FAIL:消费失败的总数
AVG(B2C):broker到Consumer的平均响应时间(毫秒)
AVG(S2C):nameserver到Consumer的平均响应时间(毫秒)
MAX(B2C): broker到Consumer的最大响应时间(毫秒)
MAX(S2C): nameserver到Consumer的最大响应时间(毫秒)
可以看到控制台里Consumer Message TPS为6w多,远大于producer的tps,且消费只从Master请求消息。
博主:测试生财
座右铭:专注测试与自动化,致力提高研发效能;通过测试精进完成原始积累,通过读书理财奔向财务自由。
csdn:https://blog.csdn.net/ccgshigao
博客园:https://www.cnblogs.com/qa-freeroad/
51cto:https://blog.51cto.com/14900374