压测工具试验
发布于: 2020 年 07 月 23 日
一、性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?
随着压力增加:
1、并发量首先上涨,系统稳定运行
2、当并发量涨到一定程度后,RT开始上涨,并发量则不再上涨,这时候系统处于最佳运行状态
3、并发量再次增长时,系统出现过载,RT直线上涨,TPS下跌,因为这时系统CPU、内存/IO等物理资源过渡消耗,处理能力下降,造成请求积压
避免系统过载的方法就是限流,阈值为系统最大并发量
二、用你熟悉的编程语言写一个 web 性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com。
程序设计:
1、运行实际测试内容模块urlInvoker
2、多线程并发模块
3、性能统计模块
package com.hyy.test;import lombok.Data;import org.springframework.http.HttpStatus;import org.springframework.http.ResponseEntity;import org.springframework.web.client.RestTemplate;import java.util.*;import java.util.concurrent.ExecutorService;import java.util.concurrent.*;// 性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?// 用你熟悉的编程语言写一个 web 性能压测工具,输入参数:URL,请求总次数,并发数。// 输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com。//程序设计//1、运行实际测试内容模块urlInvoker//2、多线程并发模块//3、性能统计模块public class PostTest { RestTemplate restTemplate = new RestTemplate(); public static void main(String[] args) { PostTest postTest = new PostTest(); postTest.test(); } public void test(){ TestRequest testRequest = new TestRequest(); testRequest.setConcurrentCount(10); testRequest.setReqCount(100); testRequest.setTarget("http://www.baidu.com"); Monitor monitor = doTest(testRequest); System.out.println("成功次数:"+monitor.getSuccess()+" 失败次数:"+monitor.getFail()+" 异常次数:"+monitor.getException()); System.out.println("平均耗时="+getAvgTime(monitor)+" 95%耗时="+getMostTime(monitor)); } /** * 根据测试入参开始测试 * @param testRequest * @return */ public Monitor doTest(TestRequest testRequest) { ExecutorService executorService = Executors.newFixedThreadPool(testRequest.getConcurrentCount()); int count = testRequest.getReqCount(); InvokeTarget invokeTarget = new UrlInvoke(); Monitor monitor = new Monitor(); for(int i=0;i<count;i++){ long start = System.currentTimeMillis(); Future<RespStatus> f = executorService.submit(new Invoke(testRequest,invokeTarget)); RespStatus respStatus = null; try { respStatus = f.get(); }catch(Exception e){ respStatus = RespStatus.EXCEPTIOIN; e.printStackTrace(); } long end = System.currentTimeMillis(); monitor.appendResult(respStatus,end-start); } return monitor; } private double getAvgTime(Monitor monitor){ long totalTime = 0; Map<String,Long> map = new HashMap(); map.put("totalTime",0l); monitor.costTimeList.forEach((a)->{ map.put("totalTime",map.get("totalTime")+a ); }); return Double.valueOf(map.get("totalTime"))/monitor.getTotal(); } /** * 对耗时排序,取前95%耗时 * @param monitor * @return */ private double getMostTime(Monitor monitor){ Collections.sort(monitor.costTimeList); double countD = monitor.getTotal() * 0.95; int count = (int)countD; Map<String,Long> map = new HashMap(); map.put("totalTime",0l); map.put("count",0l); monitor.costTimeList.forEach((a)->{ if(map.get("count") < count){ map.put("totalTime",map.get("totalTime")+a ); map.put("count",map.get("count")+1 ); } }); return Double.valueOf(map.get("totalTime"))/count; } enum RespStatus{ SUCCESS(1),FAIL(2),EXCEPTIOIN(3); private int status; RespStatus(int status){ this.status = status; } } @Data class TestRequest{ private int concurrentCount = 1; private int reqCount = 1; private String testType;//测试类型 private String target; } @Data class Monitor{ private volatile int success ; private volatile int fail; private volatile int exception; private volatile int total; List<Long> costTimeList = new ArrayList<Long>(); public Monitor appendResult(RespStatus resp,long time){ if(resp == RespStatus.SUCCESS){ this.success ++; }else if(resp == RespStatus.FAIL){ this.fail ++; }else{ this.exception++; } costTimeList.add(time); total++; return this; } } interface InvokeTarget{ public RespStatus invoke(TestRequest testRequest); } /** * 执行测试类 */ class UrlInvoke implements InvokeTarget{ public RespStatus invoke(TestRequest testRequest) { return urlHandler(testRequest.getTarget()); } public RespStatus urlHandler(String url){ RespStatus respStatus = RespStatus.FAIL; ResponseEntity resp = null; try { resp = restTemplate.postForEntity(url,null,String.class); if(resp.getStatusCode() == HttpStatus.OK){ respStatus = RespStatus.SUCCESS; } }catch (Exception e){ respStatus = RespStatus.EXCEPTIOIN; e.printStackTrace(); } return respStatus; } } class Invoke implements Callable{ private TestRequest testRequest; private InvokeTarget invokeTarget; public Invoke(TestRequest testRequest,InvokeTarget invokeTarget){ this.testRequest = testRequest; this.invokeTarget = invokeTarget; } public Object call() throws Exception { return invokeTarget.invoke(testRequest); } }}
测试1000次结果
划线
评论
复制
发布于: 2020 年 07 月 23 日阅读数: 56
版权声明: 本文为 InfoQ 作者【独孤魂】的原创文章。
原文链接:【http://xie.infoq.cn/article/25e87acd08bcc5c57de908071】。未经作者许可,禁止转载。
独孤魂
关注
还未添加个人签名 2019.04.10 加入
还未添加个人简介
评论