web 性能压测工具

用户头像
Z冰红茶
关注
发布于: 2020 年 07 月 21 日

需求:用你熟悉的编程语言写一个 web 性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com。

分析:“www.baidu.com”可以解读为最简单的get请求,且不需要处理返回值,只要获取响应状态码即可,更简单点,只要判断状态码是否等于200,如果等于200请求成功,如果不等于200请求失败;

自定义请求次数,简单循环操作即可。

要支持并发,也就是需要多线程执行请求。

通过分析,可以确定:

1、能处理http请求,且需要获取响应状态

2、可以多次循环处理

3、可以并发处理



实现:先来整体目录结构

类RequestProcessor,处理url请求,并返回响应结果

public class RequestProcessor {
private static Logger log = LoggerFactory.getLogger(RequestProcessor.class);
public RequestProcessor(String url){
this.url = url;
}
private String url;
public ResponseInfo process(){
ResponseInfo responseInfo = new ResponseInfo(url);
HttpClient client = HttpClients.createDefault();
HttpGet request = new HttpGet(url);
try {
Long start = System.currentTimeMillis();
HttpResponse response = client.execute(request);
Long end = System.currentTimeMillis();
//耗时
responseInfo.setResponseTime(end-start);
// 状态码
int responseCode = response.getStatusLine().getStatusCode();
responseInfo.setResponseCode(responseCode);
// 返回信息
responseInfo.setResponseMessage(EntityUtils.toString(response.getEntity()));
} catch (IOException e) {
e.printStackTrace();
log.error("请求异常:", e);
}
return responseInfo;
}



类ResponseInfo,影响结果类,存放url、响应时间、响应结果等信息

public class ResponseInfo {
private String url;
private Long responseTime;
private Integer responseCode;
private String responseMessage;
public ResponseInfo(){
}
public ResponseInfo(String url){
this.url = url;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Long getResponseTime() {
return responseTime;
}
public void setResponseTime(Long responseTime) {
this.responseTime = responseTime;
}
public Integer getResponseCode() {
return responseCode;
}
public void setResponseCode(Integer responseCode) {
this.responseCode = responseCode;
}
public String getResponseMessage() {
return responseMessage;
}
public void setResponseMessage(String responseMessage) {
this.responseMessage = responseMessage;
}
@Override
public String toString() {
return "ResponseInfo{" +
"url='" + url + '\'' +
", responseTime=" + responseTime +
", responseCode=" + responseCode +
", responseMessage='" + responseMessage + '\'' +
'}';
}



类StressTesting,压测入口类,输入URL,请求总次数,并发数,并发执行Url请求,并统计结果

public class StressTesting {
// 存放相应结果
private List<ResponseInfo> storage = new Vector<>();
// 请求次数
private int requestTime = 0;
// 并发数
private int concurrencyTime = 0;
// 请求地址
private String url;
private ExecutorService executorService;
public StressTesting(String url, int concurrencyTime, int requestTime){
this.url = url;
this.concurrencyTime = concurrencyTime;
this.requestTime = requestTime;
// 根据并发数设置线程池
executorService = Executors.newFixedThreadPool(concurrencyTime);
}
/**
* 执行任务
*/
public void testing(){
executorService.submit(() -> {
for(int i=0; i<requestTime; i++){
storage.add(new RequestProcessor(url).process());
}
});
executorService.shutdown();
while(true){
if(executorService.isTerminated()){
break;
}
}
// 打印统计结果
statistics();
}
/**
* 统计结果
*/
public void statistics(){
System.out.println(getAvg());
System.out.println(getPercent95());
}
/**
* 95%响应时间
* @return
*/
protected String getPercent95(){
// 排序
storage.sort((info1, info2)->{
return (int)(info1.getResponseTime()-info2.getResponseTime());
});
// 取95%
Long responseTime = storage.get((int)(storage.size()*0.95)).getResponseTime();
return "95%="+responseTime+"ms";
}
/**
* 平局响应时间
* @return
*/
protected String getAvg(){
long sum = 0l;
for(ResponseInfo info : storage){
sum += info.getResponseTime();
}
long avg = sum/storage.size();
return "avg="+avg+"ms";
}
}

测试用例,10并发,100次请求

@Test
public void testing() {
String url = "http://www.baidu.com";
new StressTesting(url, 10, 100).testing();
}

测试结果

avg=87ms
95%=162ms

V0版太简陋,重构计划:

目前只支持Get请求,请求处理器优化,支持Get、Post,支持参数等。

响应信息直接放到List保存,可以抽象一个Storage接口,支持各种方式存储。

测试结果,平均值、最大最小值、95%、99%等,抽象出结果展示借口,方便扩展各种结果。

结果展示方式优化等。

发布于: 2020 年 07 月 21 日 阅读数: 6
用户头像

Z冰红茶

关注

还未添加个人签名 2018.09.17 加入

还未添加个人简介

评论

发布
暂无评论
web 性能压测工具