1
架构师训练 第七周 作业
发布于: 2020 年 07 月 22 日
作业 1
性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?
吞吐量
性能测试时随着并发数据的增加,当服务器资源还是比较空闲时吞吐量是不断上升,当网络和服务器资源逐渐到达满载吞吐量会到达一个高峰值。当并发数还在不断的增加服务器处理不过来时,吞吐量会逐渐下降,直至系统崩溃。
响应时间
当服务器资源还比较空闲时响应时间是比较短的,当并发量的不断增加,系统资源不断消耗,新的请求处理不过来,响应时间会逐渐变长。当并发量还在不断的增加是就会导致服务器资源耗尽失去响应。
作业 2.
用你熟悉的语言写一个web压测工具,输入参数:URL, 请求总次数,并发次数。输出参数平均响应时间。用这个测试工具以10并发,100次请求压测 www.baidu.com
类图
测试Case模板类
/** * TestCase 模板 * * @author Lee * @date 2020/7/21 16:20 */public abstract class BaseTestCase implements Callable { /** * case 执行抽象方法 * * @return */ public abstract Result execution();}
测试case
/** * 测试case类 * @author Lee */public class TestGetRequest extends BaseTestCase { /** * 测试用 url */ private String url; public TestGetRequest(String url) { this.url = url; } /** * 请求执行 * * @return Result */ @Override public Result execution() { CloseableHttpClient httpClient = HttpClients.createDefault(); // 创建Get请求 HttpGet httpGet = new HttpGet(this.url); long t1 = System.currentTimeMillis(); CloseableHttpResponse response = null; try { response = httpClient.execute(httpGet); } catch (IOException e) { e.printStackTrace(); } long t2 = 0L; Result result = new Result(); // 访问成功 if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { t2 = System.currentTimeMillis(); result.setResponseTime(t2 -t1); result.setSuccess(true); } // 访问失败 else { t2 = System.currentTimeMillis(); result.setResponseTime(t2 -t1); result.setSuccess(false); } return result; } @Override public Object call() throws Exception { return execution(); }}
测试结果类
/** * 测试返回结果 * * @author Lee * @date 2020/7/21 9:00 */public class Result { /** * 响应时间 */ private Long responseTime; /** * 访问是否成功 */ private boolean success; public Long getResponseTime() { return responseTime; } public void setResponseTime(Long responseTime) { this.responseTime = responseTime; } public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; }}
测试报告模板
/** * 测试报告模板 * * @author rikun */public abstract class BaseTestReport { /** * 测试报告生成 * * @param results */ public abstract void calResult(List<Future<Result>> results);}
测试报告
/** * 测试报告 * * @author Lee * @date 2020/7/21 8:43 */public class TestReport extends BaseTestReport { private int numberOfTests; public TestReport(int numOfTests) { this.numberOfTests = numOfTests; } /** * 计算出测试结果 * * @param results * @return */ @Override public void calResult(List<Future<Result>> results) { // 取出每次的请求的响应时间 List<Long> list = new ArrayList<>(); try{ for (Future<Result> item: results) { Result result = item.get(); list.add(result.getResponseTime()); } } catch (ExecutionException | InterruptedException ignored) { ignored.printStackTrace(); } // 按大小排序 list.sort(Comparator.comparingLong(Long:: longValue)); // 求 95% 响应时间 序号 int ninetyFiveRT = BigDecimal.valueOf(numberOfTests).multiply(BigDecimal.valueOf(0.95D)).setScale(0, BigDecimal.ROUND_UP).intValue(); // 求 平均响应时间 double avgRt = list.stream().mapToLong(Long::longValue).average().getAsDouble(); // 打印出测试结果 System.out.println("平均响应时间: " + BigDecimal.valueOf(avgRt).setScale(0, BigDecimal.ROUND_UP) + ";"); System.out.println("95%响应时间: " + list.get(ninetyFiveRT) + ";"); }}
测试任务设定类
/** * 任务设定 * * @author rikun */public class TaskConfiguration { /** * 并发数 */ private int concurrentNum; /** * 批次数 */ private int numberOfTests; /** * 线程池 */ private ExecutorService pool; /** * 测试类型 */ private BaseTestCase testCase; /** * 测试报告 */ private BaseTestReport testReport; /** * 测试计划配置 * * @param concurrentNum int * @param numberOfTests int */ public TaskConfiguration(int concurrentNum, int numberOfTests) { this.concurrentNum = concurrentNum; this.numberOfTests = numberOfTests; this.pool = new ThreadPoolExecutor(numberOfTests, numberOfTests, 0, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); } /** * 设置测试case * * @param testCase */ public void setTestCase(BaseTestCase testCase) { this.testCase = testCase; } /** * 设置测试报告 * * @param testReport */ public void setTestReport(BaseTestReport testReport) { this.testReport = testReport; } /** * 多批次执行 * * @throws InterruptedException */ public void testExecute() throws InterruptedException { if (this.testCase == null) { System.out.println("请设定测试case,否则测试无法进行"); return; } BigDecimal val1 = BigDecimal.valueOf(concurrentNum); BigDecimal val2 = BigDecimal.valueOf(numberOfTests); int result = val2.divide(val1, BigDecimal.ROUND_UP).intValue(); List<Future<Result>> results = new ArrayList<>(); // 将请求分批发送 for (int i = 0; i< result; i++) { int size = concurrentNum; if ( i+1 == result) { size = numberOfTests - (concurrentNum * i); } results.addAll(singleExecution(size)); } // 释放资源 pool.shutdown(); if (this.testReport == null) { System.out.println("请设定测试报告,否则无法查看测试结果"); } else { this.testReport.calResult(results); } } /** * 单批次执行 * * @throws InterruptedException */ private List<Future<Result>> singleExecution(int size) throws InterruptedException { List<Callable<Result>> tasks = new ArrayList<>(); for (int i = 0; i< size; i++) { tasks.add(this.testCase); } // 批量执行任务 return pool.invokeAll(tasks); }}
测试执行
/** * 执行测试 * * @author Lee */public class Client { public static void main(String[] args) throws ExecutionException, InterruptedException { int numberOfTests = 100; // 测试的并发数,请求数 设定 TaskConfiguration taskExecution = new TaskConfiguration(10, numberOfTests); // 设定测试case taskExecution.setTestCase(new TestGetRequest("http://www.baidu.com")); // 设定测试报告 taskExecution.setTestReport(new TestReport(numberOfTests)); // 执行测试计划 taskExecution.testExecute(); }}
测试结果
平均响应时间: 27;95%响应时间: 67;
划线
评论
复制
发布于: 2020 年 07 月 22 日阅读数: 60
版权声明: 本文为 InfoQ 作者【李君】的原创文章。
原文链接:【http://xie.infoq.cn/article/75cae57b9c6db4aa0a67a47ef】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
李君
关注
结硬寨,打呆仗。 2018.09.11 加入
还未添加个人简介
评论