上周项目引入了一个RocketMq(以下简称rmq)中间件,完成基本功能测试以后,业务方希望增加一轮压测,看下生产、消费端的Tps、延时和响应时间,和业务方对了一波压测方案以后,决定使用rmq自带的压测工具,rocketmq-benchmark(以下简称rmq-benchmark)开始进行压测。
背景如下
通常,压测完,然后把结果整理出来,汇报给业务方,由他们自己决定是否满足其使用要求即可,
如下截图:
先铺垫一下,rmq-benchmark基本的参数:
sh producer.sh -n ip:port -t perf-test8 -w 32 -s 5120 -q 5000000
-ri 1000 >> product5knode.txt && tail -f product5knode.txt
-n:namerserver服务的ip和端口号
-t:指定topicName
-w:线程数
-s:发送消息的大小
-q:总共发送的消息
-ri:打印统计结果的间隔
上述命令的意思是:往某个消息中间件的perf-test8 topic,发送5000000条消息,每条消息的大小是5120B(5kb),统计日志每秒打印一次,并输出到 product5knode.txt文档里。
业务方对整体的压测结果还是比较满意的,但其中一个场景,业务方觉得生产的tps在20000左右太高了,他们目前的tps最多200,想让我们补测一种场景,那就是生产者tps在200左右,观察下rmq集群整体的情况如何。
需求分析过程
“他们目前的tps最多200,想让我们补测一种场景,那就是生产者tps在200左右,观察下rmq集群整体的情况如何。”,说白了,就是控制生产者tps在200左右的时候,整个rmq集群的基本状态是什么样的。
针对这种场景,我还专门去查了rmq官方文档,发现rmq-benchmark工具,无论是老版和最新版,都没有控制生产者tps的参数。
咋整?我当时想了两种方案,
1、用Java开发一个rocketmq的生产者工具。
2、改下rmq-benchmark的源码。
对比两种方案,前者相对简单些,毕竟在自己可操作范围内,后者要修改源码,前提是拉取源码到本地,然后看懂源码修改后,再打成jar 包才行,难度较大。
开发一个rocketmq的生产者工具
我当时通过百度、chatgpt等手段,用Java语言写出来这个工具,如下源码:有点粗糙哈,
import com.alibaba.fastjson.JSON;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import com.google.common.util.concurrent.RateLimiter;
import org.apache.rocketmq.remoting.exception.RemotingException;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class RocketMqProducter {
private static AtomicInteger tpsMessageCount = new AtomicInteger(0);
private static AtomicInteger failMessageCount = new AtomicInteger(0);
private static AtomicInteger successMessageCount = new AtomicInteger(0);
private static AtomicInteger totalMessageCount = new AtomicInteger(0);
static int threadCount = 0;
public static void main(String[] args) throws MQClientException {
int length = 32000; // 32,000 characters
StringBuilder largeString = new StringBuilder();
// Generate the string with 32,000 characters
for (int i = 0; i < length; i++) {
largeString.append('A'); // You can use any character you like
}
String result = largeString.toString();
System.out.println("Generated string length: " + result.length());
DefaultMQProducer produce