架构师训练营第 7 周作业
作业内容
性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?
用熟悉的编程语言写一个web性能压测工具
输入参数:
测试URL
请求总次数
并发数
输出参数:
平均响应时间
95%响应时间
压测内容:
用该工具以10并发,总计100次的请求压测https://www.baidu.com
作业1:性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?
系统性能压测一般包括:性能测试、负载测试和压力测试三个阶段。
我们首先现来看一下吞吐量与并发数以及响应时间的关系:吞吐量=响应时间(ms)1000∗并发数
随着并发数的增加,系统运行在性能测试阶段,响应时间会缓慢增加,吞吐量则会快速上升;
当系统的某项或多项性能指标达到安全临界时,如果并发压力继续增加,系统的响应时间增速会加快,吞吐量增速变缓甚至出现下降;
继续增加并发压力,系统进入压力测试阶段,由于超过安全负载,响应时间会极速增加,吞吐量也会快速下降,直至系统崩溃无法提供服务。
上述描述是在正常逐渐增加压力的情况下进行测试,由于真实环境的流量具有不稳定性,为了能够更好地获取系统性能指标,还需要进行稳定性测试。
如果不均匀地增加系统并发压力,由于大量缓存失效等原因,系统的压力临界值会提前到来。
下面附上老师课件关于TPS和响应时间随着并发请求增加的情况下的能力变化示意图
作业二:用熟悉的编程语言写一个web性能压测工具
实现思路:
1. 先实现访问url的工具类(我只实现了get方法,返回自定义的HttpResponse对象);
2. 再去写压测实现类,主要方法包括:
a. 带参构造方法,可以指定压测并发数,压测总次数以及压测地址等信息;
b. 获取压测平均响应时间方法;
c. 获取指定n%响应时间方法;
d. 打印压测结果方法。
3. 压测测试类
测试输出结果:
下面是该测试工具的相关源码
/** * 自定义请求响应类 */public class HttpResponse { // 响应内容 private String content; // 响应时间 private long respTime; public String getContent() { return content; } public void setContent(String content) { this.content = content; } public long getRespTime() { return respTime; } public void setRespTime(long respTime) { this.respTime = respTime; } @Override public String toString() { return "HttpResponse{" + "content='" + content + '\'' + ", respTime='" + respTime + "ms'}"; }}
/** * 请求访问工具类 */public class HttpClient { /** * 获取连接信息 * * @param url * @return */ private static URLConnection getConnection(String url) { URLConnection connection = null; if (Optional.ofNullable(url).isPresent()) { try { connection = new URL(url).openConnection(); connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); } catch (IOException e) { e.printStackTrace(); } } return connection; } /** * GET方式请求简单实现 * * @param url * @return */ public static HttpResponse get(String url) { HttpResponse response = new HttpResponse(); StringBuilder content = new StringBuilder(); URLConnection connection = getConnection(url); try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { long start = System.currentTimeMillis(); connection.connect(); String line = null; while ((line = in.readLine()) != null) { content.append(line); } response.setContent(content.toString()); response.setRespTime(System.currentTimeMillis() - start); } catch (IOException e) { e.printStackTrace(); } return response; }}
/** * 压力测试模拟器 */public class Simulator { private String url = null; private int sbc = 1; private int times = 1; /** * 测试模拟器构造方法 * * @param url 测试地址 * @param sbc 并发数 * @param times 请求总次数 */ public Simulator(String url, int sbc, int times) { this.url = url; this.sbc = sbc; this.times = times; } /** * 启动压测 * @return * @throws InterruptedException */ public List<HttpResponse> start() throws InterruptedException { List<HttpResponse> respList = new ArrayList<>(); ThreadPoolExecutor executor = new ThreadPoolExecutor(sbc, sbc, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); for (int i = 0; i < this.times; i++) { executor.execute(() -> { HttpResponse resp = HttpClient.get(this.url); respList.add(resp); }); } while (executor.getActiveCount() > 0) { Thread.sleep(100); } executor.shutdown(); return respList; } /** * 获取平均响应时间 * * @param respList * @return */ public long getAvgRespTime(List<HttpResponse> respList) { return Optional.ofNullable(respList).orElse(new ArrayList<>()).stream() .map(HttpResponse::getRespTime) .collect(Collectors.averagingLong(Long::longValue)).longValue(); } /** * 获取${percent}%响应时间 * * @param respList * @return */ public long getAvgRespTime(List<HttpResponse> respList, int percent) { long avgRespTime = 0L; Optional<List<HttpResponse>> respTimesOptional = Optional.ofNullable(respList); if (respTimesOptional.isPresent()) { avgRespTime = respTimesOptional.get().stream() .map(HttpResponse::getRespTime) .sorted() .collect(Collectors.toList()) .get(Math.max(Math.floorDiv(respList.size() * percent, 100) - 1, 0)); } return avgRespTime; } /** * 打印压测结果 * * @param respList */ public void print(List<HttpResponse> respList) { System.out.println(String.format("并发 %d 访问 %s,总计访问 %d 次,压测结果:", this.sbc, this.url, this.times)); System.out.println(String.format("平均响应时间: %d ms", this.getAvgRespTime(respList))); System.out.println(String.format("95%s响应时间: %d ms", "%", this.getAvgRespTime(respList, 95))); }}
/** * 压力测试baidu */public class SimulatorTest { @Test public void testSimulator() throws InterruptedException { String url = "http://www.baidu.com"; int sbc = 10; int times = 100; Simulator testSimulator = new Simulator(url, sbc, times); List<HttpResponse> respList = testSimulator.start(); testSimulator.print(respList); }}
王友
懒是一种艺术 2018.03.26 加入
间歇性自律,持续性懒散,真的很懒!
评论