Web 性能压测工具(训练营第七课)
发布于: 2020 年 07 月 22 日
作业
用你熟悉的编程语言写一个 web 性能压测工具
输入参数:URL,请求总次数,并发数
输出参数:平均响应时间,95% 响应时间
测试目标:用这个测试工具以 10 并发、100 次请求压测 www.baidu.com。
解题
application.properties
perftest.url=https://www.baidu.comperftest.total_request=100perftest.concurrent_count=10perftest.interval_per_request=100
PerfTestExecutor
采用 OkHttpClient 来发送请求,通过 CountDownLatch 来控制启动和结束
@Slf4jpublic class PerfTestExecutor { private final OkHttpClient okHttpClient; private final PerfTestConf perfTestConf; private final Request perfTestRequest; private final int loopCount; private final Map<String, List<Long>> requestTimesMap = new ConcurrentHashMap<>(); private final CountDownLatch startSignal; private final CountDownLatch doneSignal; public PerfTestExecutor(OkHttpClient okHttpClient, PerfTestConf perfTestConf) { assert perfTestConf.getConcurrentCount() > 0; assert perfTestConf.getTotalRequest() >= perfTestConf.getConcurrentCount(); this.okHttpClient = okHttpClient; this.perfTestConf = perfTestConf; perfTestRequest = new Request.Builder().url(perfTestConf.getUrl()).build(); loopCount = (int) Math.ceil((double) perfTestConf.getTotalRequest() / perfTestConf.getConcurrentCount()); System.out.println("loopCount: " + loopCount); this.startSignal = new CountDownLatch(1); this.doneSignal = new CountDownLatch(perfTestConf.getConcurrentCount()); init(); } private void init() { for (int j = 0; j < perfTestConf.getConcurrentCount(); j++) { final String threadName = "Thread-" + j; new Thread(() -> { try { startSignal.await(); } catch (InterruptedException e) { e.printStackTrace(); } long requestTime; for (int i = 0; i < loopCount; i++) { long startTimeInMilli = System.currentTimeMillis(); try (Response response = okHttpClient.newCall(perfTestRequest).execute()) { log.info("Response " + i + " from " + perfTestConf.getUrl()); requestTime = System.currentTimeMillis() - startTimeInMilli; requestTimesMap.computeIfAbsent(threadName, k -> new ArrayList<>()).add(requestTime); if (perfTestConf.getIntervalPerRequest() > 0 && requestTime < perfTestConf.getIntervalPerRequest()) { Thread.sleep(perfTestConf.getIntervalPerRequest() - requestTime); } } catch (InterruptedException | IOException e) { log.warn("Exception", e); } } doneSignal.countDown(); }).start(); } } public void start() { startSignal.countDown(); } public void await() throws InterruptedException { doneSignal.await(); } public List<Long> getRequestTimeList() { return requestTimesMap.values().stream().flatMap(Collection::stream).sorted().collect(Collectors.toList()); }}PerfTestApplication
@SpringBootApplicationpublic class PerfTestApplication implements ApplicationRunner { @Autowired private OkHttpClient okHttpClient; @Autowired private PerfTestConf perfTestConf; public static void main(String[] args) { SpringApplication.run(PerfTestApplication.class, args); } @Override public void run(ApplicationArguments args) throws Exception { System.out.println(perfTestConf); PerfTestExecutor testExecutor = new PerfTestExecutor(okHttpClient, perfTestConf); testExecutor.start(); testExecutor.await(); generateStatistics(testExecutor.getRequestTimeList()); } public void generateStatistics(List<Long> longList) { // longList.forEach(System.out::println); double average = longList.stream().mapToLong(l -> l).average().getAsDouble(); int p95Count = (int) Math.floor(perfTestConf.getTotalRequest() * 0.95); long p95 = longList.stream().mapToLong(l -> l).skip(p95Count - 1).findFirst().getAsLong(); System.out.println("Average: " + average); System.out.println("95%: " + p95); }}Result
Average: 35.4195%: 206// 下面是所有的 100 个请求时间101111111111111111111111121212121212121212121212121213131313131313131313131313131313131313131414141414141414141414141415151515151515151516171717171717171818181818181822364256576269206206206206206206206206206206
划线
评论
复制
发布于: 2020 年 07 月 22 日 阅读数: 28
看山是山
关注
还未添加个人签名 2018.11.16 加入
还未添加个人简介
评论