《架构师训练营》-第七周-作业

作业要求

  1. 性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?
  2. 用你熟悉的编程语言写一个 web 性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com。

1. 并发数与性能对照图

看下图可以得知:

  1. 当服务器分配给系统的资源越多时,系统的TPS就越高;b点最佳
  2. 当服务器资源分配到上限时,系统的TPS也达到了上限,这时候如果再分配资源,系统的TPS反而下降;达到了c点
  3. 当服务器资源分配超载时,系统就有可能崩溃。达到了d点

在b点时,可以发挥系统最佳性能(不会浪费系统资源,同时又有一定的负载能力)。可以根据项目情况选择在b点的左右浮动
《架构师训练营》-第七周-作业_第1张图片

看下图可以得知:

  1. 当并发数越大,系统的响应时间就越慢;
  2. 当并发数超过服务器的极限,响应时间会大大提高;
    在这里插入图片描述

2.压测工具

源码地址:https://github.com/CNXMBuyu/study_2020/tree/master/geek/src/main/java/cn/hgy/week7

注意点

  1. CountDownLatch的使用,得到测试结果需要所有的线程都执行完成
  2. ThreadPoolExecutor构造函数,核心线程数为最大并发数,等待队列为请求总数
  3. 如果使用域名,可能会在首次请求时,耗费大量时间进行域名解析(PS:感谢何敏伟同学以及吴炳华同学指点)

作业结果

开始执行测测试用例。。。。。。
执行测测试用例结束。。。。。。耗时:2198
测试结果为:测试地址:url=http://14.215.177.39, 总次数=100, 失败次数=0, 平均响应时间=54, 95%响应时间=123
按顺序执行响应结果如下:
123,123,123,123,123,123,123,123,123,123,37,41,44,53,44,50,49,53,52,49,36,39,44,40,45,46,44,49,48,38,36,36,35,37,37,42,43,111,43,45,46,49,36,46,46,99,48,50,45,47,38,50,40,46,46,45,46,46,37,37,38,42,46,44,45,43,69,77,44,43,44,42,52,42,57,50,39,48,37,41,42,48,40,41,47,40,38,40,44,48,44,45,49,46,38,35,43,36,36,181,
按响应顺序排序之后结果如下:
35,35,36,36,36,36,36,36,37,37,37,37,37,37,38,38,38,38,38,39,39,40,40,40,40,40,41,41,41,42,42,42,42,42,43,43,43,43,43,44,44,44,44,44,44,44,44,44,45,45,45,45,45,45,46,46,46,46,46,46,46,46,46,46,47,47,48,48,48,48,48,49,49,49,49,49,50,50,50,50,52,52,53,53,57,69,77,99,111,123,123,123,123,123,123,123,123,123,123,181,

核心代码

TestHelper.java

package cn.hgy.week7;


import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 测试助手
 *
 * @author guoyu.huang
 * @since 2020-07-22
 */
public class TestHelper {

    /**
     * 测试
     *
     * @param url
     * @param totalRequestCount
     * @param concurrencyCount
     * @return
     */
    public static TestResult test(String url, int totalRequestCount, int concurrencyCount) {

        // 等待所有线程都执行完之后,才返回
        CountDownLatch countDownLatch = new CountDownLatch(totalRequestCount);
        // 分配线程,核心线程数为最大并发数,等待队列为请求总数
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(concurrencyCount, concurrencyCount, 0, TimeUnit.SECONDS, new LinkedBlockingDeque<>(totalRequestCount));

        // 测试结果
        TestResult result = new TestResult();
        result.setUrl(url);

        // 添加都线程队列
        int count = totalRequestCount;

        System.out.println("开始执行测测试用例。。。。。。");
        long allBegin = System.currentTimeMillis();

        while (count > 0) {

            threadPoolExecutor.submit(() -> {
                try {
                    HttpClient client = HttpClientBuilder.create().build();
                    HttpGet httpGet = new HttpGet(url);
                    long begin = System.currentTimeMillis();
                    HttpResponse response = client.execute(httpGet);
                    if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                        result.addResponse(Long.valueOf(System.currentTimeMillis() - begin).intValue());
                    } else {
                        result.addResponse(-1);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                }
            });
            count--;
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("执行测测试用例结束。。。。。。耗时:" + (System.currentTimeMillis() - allBegin));
        return result;
    }
}

TestResult.java

package cn.hgy.week7;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * 测试结果类
 *
 * @author guoyu.huang
 * @since 2020-07-22
 */
public class TestResult {

    private String url;
    private List<Integer> responseTimeList = new CopyOnWriteArrayList<>();
    private Integer avgResponseTime;
    private Integer _95ResponseTime;

    public void addResponse(Integer responseTime) {
        responseTimeList.add(responseTime);
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public List<Integer> getResponseTimeList() {
        return responseTimeList;
    }

    public void setResponseTimeList(List<Integer> responseTimeList) {
        this.responseTimeList = responseTimeList;
    }

    public Integer getAvgResponseTime() {
        int sum = 0;
        int count = 0;
        for (Integer l : responseTimeList) {
            sum += (l < 0 ? 0 : l.intValue());
            count += (l < 0 ? 0 : 1);
        }
        return sum / count;
    }

    public void setAvgResponseTime(Integer avgResponseTime) {
        this.avgResponseTime = avgResponseTime;
    }

    public Integer get_95ResponseTime() {
        List<Integer> list = responseTimeList.stream().sorted().collect(Collectors.toList());
        int index = Double.valueOf(list.size() * 0.95).intValue();
        return list.get(index);
    }

    public void set_95ResponseTime(Integer _95ResponseTime) {
        this._95ResponseTime = _95ResponseTime;
    }

    @Override
    public String toString() {
        return "测试地址:url=" + url + ", 总次数=" + responseTimeList.size() + ", 失败次数=" +
                responseTimeList.stream().filter(l -> {
                    return l == -1;
                }).count() + ", 平均响应时间=" + getAvgResponseTime() +
                ", 95%响应时间=" + get_95ResponseTime();
    }
}

Main.java

package cn.hgy.week7;

import java.util.stream.Collectors;

/**
 * @author guoyu.huang
 * @since 2020-07-22
 */
public class Main {

    public static void main(String[] args) {
        long begin = System.currentTimeMillis();
        // 将域名解析成IP
        TestResult testResult = TestHelper.test("http://14.215.177.39", 100, 10);
        System.out.println("测试结果为:" + testResult.toString());
        System.out.println("按顺序执行响应结果如下:");
        testResult.getResponseTimeList().forEach(l -> {
            System.out.print(l + ",");
        });
        System.out.println();
        System.out.println("按响应顺序排序之后结果如下:");
        testResult.getResponseTimeList().stream().sorted().forEach(l -> {
            System.out.print(l + ",");
        });
    }
}

你可能感兴趣的:(#,架构师训练营)