Week7 作业
发布于: 2020 年 07 月 22 日
1、性能测试的时候,随着并发压力的增加,系统的响应时间和吞吐量如何变化,为什么?
吞吐量(TPS)=(1000/响应时间ms)*并发数
随着并发压力的增加,吞吐量会先有一个迅速增加的过程,响应时间比较平稳。此时系统的资源逐渐开始被利用起来;当继续增大并发量,TPS增加幅度会减少,逐渐达到最大值。响应时间会略有增加,达到系统的最大负荷点;继续加压,会出现系统资源不够用的情况,用户请求出现排队现象,响应时间会变得很长,从而影响吞吐量;最终响服务器资源耗尽,响应时间无限长,没有吞吐量。
2、用熟悉的语言编写一个性能压测工具,输入url,请求总次数,并发数。输出参数:平均响应时间,95%响应时间。用这个压测工具以10的并发数,100次请求压测www.baidu.com
思路:将多次请求分成多个子任务,由多个线程处理。最后对测试结果进行汇总分析。jdk8以上可以用并行流简化处理。jdk7可直接使用ForkJoinPoll.
实现代码:
LoadTestTask
package camp.week7;import lombok.extern.slf4j.Slf4j;import sun.net.www.http.HttpClient;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.util.ArrayList;import java.util.List;import java.util.concurrent.RecursiveTask;@Slf4jpublic class LoadTestTask extends RecursiveTask<List<ExecutionResult>> { private final long[] sampleNumbers; private final int start; private final int end; private int concurrentNumber = 10; private String url; private LoadTestTask(long[] sampleNumbers, int start, int end, int concurrentNumber, String url) { super(); this.sampleNumbers = sampleNumbers; this.start = start; this.end = end; this.concurrentNumber = concurrentNumber; this.url = url; } public LoadTestTask(long[] sampleNumbers, int concurrentNumber, String url) { super(); this.sampleNumbers = sampleNumbers; this.start = 0; this.end = sampleNumbers.length; this.concurrentNumber = concurrentNumber; this.url = url; } @Override protected List<ExecutionResult> compute() { int length = end - start; if (length <= sampleNumbers.length / concurrentNumber) { try { return computeSequentially(); } catch (Exception e) { log.error(e.getMessage(), e); } } LoadTestTask leftTask = new LoadTestTask(sampleNumbers, start, start + length / 2, concurrentNumber, url); leftTask.fork(); LoadTestTask rightTask = new LoadTestTask(sampleNumbers, start + length / 2, end, concurrentNumber, url); rightTask.fork(); List<ExecutionResult> rightResult = null; try { rightResult = rightTask.get(); } catch (Exception e) { log.error(e.getMessage(), e); } List<ExecutionResult> leftResult = leftTask.join(); ArrayList<ExecutionResult> results = new ArrayList<>(); results.addAll(leftResult); results.addAll(rightResult); return results; } private List<ExecutionResult> computeSequentially() throws Exception { List<ExecutionResult> list = new ArrayList<>(); for (int i = start; i < end; i++) { long startTime = System.currentTimeMillis(); HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("GET"); connection.connect(); int responseCode = connection.getResponseCode(); String response = null; if (responseCode == HttpURLConnection.HTTP_OK) { InputStream inputStream = connection.getInputStream(); response = streamToString(inputStream); } long finishTime = System.currentTimeMillis(); ExecutionResult executionResult = ExecutionResult.builder() .id(sampleNumbers[i]) .threadName(Thread.currentThread().getName()) .startTime(startTime) .finishTime(finishTime) .executionTime(finishTime - startTime) .response(response) .build(); list.add(executionResult); } return list; } private String streamToString(InputStream is) { String result = ""; try { byte[] bytes = new byte[0]; bytes = new byte[is.available()]; is.read(bytes); result = new String(bytes); } catch (Exception e) { log.error(e.getMessage(), e); } return result; }}
AggregationAnalyzer
package camp.week7;import java.util.Comparator;import java.util.List;import java.util.OptionalDouble;import java.util.stream.Collectors;public class AggregationAnalyzer { public static AggregationReport analyze(List<ExecutionResult> results) { List<ExecutionResult> sortedResult = results.stream() .sorted(Comparator.comparing(ExecutionResult::getExecutionTime)) .collect(Collectors.toList()); double avg = sortedResult.stream().mapToLong(ExecutionResult::getExecutionTime).average().orElse(0d); int ninetyFive = (int) (sortedResult.size() * 0.95); int fifty = (int) (sortedResult.size() * 0.50); AggregationReport report = AggregationReport.builder() .minResTime(sortedResult.get(0).getExecutionTime()) .maxResTime(sortedResult.get(sortedResult.size() - 1).getExecutionTime()) .avgResTime(avg) .fiftyResTime(sortedResult.get(fifty).getExecutionTime()) .ninetyFiveResTime(sortedResult.get(ninetyFive).getExecutionTime()) .build(); return report; }}
ExecutionResult
package camp.week7;import lombok.Builder;import lombok.Data;@Data@Builderpublic class ExecutionResult { private Long id; private Long startTime; private Long finishTime; private Long executionTime; private String threadName; private String response;}
AggregationReport
package camp.week7;import lombok.Builder;import lombok.Data;@Data@Builderpublic class AggregationReport { private long maxResTime; private long minResTime; private double avgResTime; private long ninetyFiveResTime; private long fiftyResTime; public String toString() { StringBuilder sb = new StringBuilder("Aggregation Report:"); sb.append(" min->").append(this.getMinResTime()); sb.append(" max->").append(this.getMaxResTime()); sb.append(" avg->").append(this.getAvgResTime()); sb.append(" 50%->").append(this.getFiftyResTime()); sb.append(" 95%->").append(this.getNinetyFiveResTime()); return sb.toString(); }}
LoadTestTool
package camp.week7;import java.util.ArrayList;import java.util.Comparator;import java.util.List;import java.util.concurrent.ForkJoinPool;import java.util.stream.Collectors;import java.util.stream.LongStream;public class LoadTestTool { public static void main(String[] args) { long sampleNumber = 100; int concurrentNumber = 10; String url = "http://www.baidu.com"; long[] sampleNumbers = LongStream.rangeClosed(1, sampleNumber).toArray(); List<ExecutionResult> results = new ForkJoinPool(concurrentNumber) .invoke(new LoadTestTask(sampleNumbers, concurrentNumber, url)); AggregationReport report = AggregationAnalyzer.analyze(results); System.out.println(report); }}
结果输出:
Aggregation Report: min->46 max->729 avg->105.52 50%->61 95%->273
划线
评论
复制
发布于: 2020 年 07 月 22 日阅读数: 45
TiK
关注
还未添加个人签名 2018.04.26 加入
还未添加个人简介
评论