最近公司测试同学想要对rpc(dubbo)服务进行压测,通过之前使用过集团(淘宝)压测工具stresstest对其进行了一定的改造使用,目前已改造出最简单版本 https://github.com/ChenBoEason/stress-tool ,对此感兴趣的同学可以拉取下来使用,也可以自己改造出自己适合使用的代码。使用过淘宝的stresstest的同学其实看这个会发现很相同,并没有啥多大区别,我单独弄出来的原因在于对其进行改造出适合自己的一个压测工具。如果你觉得还可以可以个我点歌star。谢谢
思想
简单介绍一下设计,并发数、总请求次数,均摊到每个并发上就形成了一个访问多次请求。为了统计请求结果,同时对结果进行分析,采用了CyclicBarrier、CountDownLatch等技术,其实这个工具的的主要点就在于多个线程执行,一个总任务线程最后统计。
核心代码如下:
this.warmUp(warmUpTime, stressTask);
int everyThreadCount = totalRequests / concurrencyLevel;
CyclicBarrier threadStartBarrier = new CyclicBarrier(concurrencyLevel);
CountDownLatch threadEndLatch = new CountDownLatch(concurrencyLevel);
AtomicInteger failedCounter = new AtomicInteger();
StressContext stressContext = new StressContext();
stressContext.setTestService(stressTask);
stressContext.setEveryThreadCount(everyThreadCount);
stressContext.setThreadStartBarrier(threadStartBarrier);
stressContext.setThreadEndLatch(threadEndLatch);
stressContext.setFailedCounter(failedCounter);
ExecutorService executorService = Executors.newFixedThreadPool(concurrencyLevel);
List<StressThreadWorker> workers = new ArrayList(concurrencyLevel);
int realTotalRequests;
StressThreadWorker worker;
for(realTotalRequests = 0; realTotalRequests < concurrencyLevel; ++realTotalRequests) {
worker = new StressThreadWorker(stressContext, everyThreadCount);
workers.add(worker);
}
for(realTotalRequests = 0; realTotalRequests < concurrencyLevel; ++realTotalRequests) {
worker = (StressThreadWorker)workers.get(realTotalRequests);
executorService.submit(worker);
}
try {
threadEndLatch.await();
} catch (InterruptedException var21) {
log.error("InterruptedException", var21);
}
executorService.shutdownNow();
realTotalRequests = everyThreadCount * concurrencyLevel;
int failedRequests = failedCounter.get();
StressResult stressResult = new StressResult();
StressTester.SortResult sortResult = this.getSortedTimes(workers);
List<Long> allTimes = sortResult.allTimes;
stressResult.setAllTimes(allTimes);
List<Long> trheadTimes = sortResult.trheadTimes;
long totalTime = (Long)trheadTimes.get(trheadTimes.size() - 1);
stressResult.setTestsTakenTime(totalTime);
stressResult.setFailedRequests(failedRequests);
stressResult.setTotalRequests(realTotalRequests);
stressResult.setConcurrencyLevel(concurrencyLevel);
stressResult.setWorkers(workers);
对于工具的代码不过多介绍,把代码拉下来看看写个demo运行断点调试一下我相信大部分人就懂了很多了。
使用
在使用方面也很简单,对其核心代码进行了一些封装之后就可以使用了,在源码里由很简单的demo,这里我展示一个对dubbo服务进行压测的代码,首先创建dubbo消费者配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="consumer" />
<!-- 使用multicast广播注册中心暴露发现服务地址 -->
<dubbo:registry address="zookeeper://ip:2181" />
<!--消费者配置-->
<dubbo:consumer check="true" group="xxx"/>
<dubbo:reference id="demoRSV" interface="com.xxx.dubbo.IDemoRSV"/>
</beans>
java代码
public static void main(String[] args) {
// 加载dubbo配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"consumer.xml"});
context.start();
//获取需要测试的server
IDemoRSV demoRSV = (IDemoRSV) context.getBean("demoRSV") ;
StressResult stressResult = StressStore.test(1,10, new StressTask() {
long count = 0;
@Override
public Object doTask() throws Exception {
//dubbo请求
DemoReqDTO demoReqDTO = new DemoReqDTO();
demoReqDTO.setName("测试");
DemoRespDTO demoRespDTO = demoRSV.sayHello(demoReqDTO);
System.out.println("Result"+count+++" :" + respDTO.toString());
return null;
}
}, 0);
//数据格式化
String str = StressStore.format(stressResult);
System.out.println(str);
}
大概的样子就是这样,这是一个很简单的压测工具,没有什么技术含量,喜欢的同学可以给我点个小心心。