架构师训练营第七周作业
发布于: 2020 年 11 月 09 日
性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?
随着并发压力增加,系统响应时间会逐渐增大,压力到达一定阈值后,响应时间会急剧增加,直至系统崩溃
随着并发压力增加,吞吐量首先会逐渐增加,增加幅度会逐渐放缓,压力到达一定阈值后吞吐量会逐渐减小,幅度会越来越大,直至系统崩溃
导致以上变化的原因为:
并发数较小时,系统资源足够,系统收到请求后无需等待或等待时间较短,所以响应时间变化不大,而吞吐量 = (1000 / 响应时间ms) x 并发数,所以吞吐量随并发数增加而增加;
并发数较大时,系统资源不足以分配给每个请求,CPU需要调度系统资源,如在内存耗尽的情况下使用虚拟内存,虚拟内存的读写速度远低于内存的读写速度,响应时间相应变长,另一方面,线程之间切换也有时间开销,因此吞吐量会逐渐减小
性能压测工具
开发语言为Java,使用CloseableHttpClient完成请求
package com.colin.benchmarker;import java.util.Collections;import java.util.LinkedList;import java.util.List;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicInteger;import org.apache.http.ConnectionReuseStrategy;import org.apache.http.HttpResponse;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.protocol.HttpContext;public class CustomBenchMarker { /** * 返回时间 */ List<Long> responseTimes; /** * 测试地址 */ String url; /** * 并发数 */ int concurrency; /** * 总请求次数 */ AtomicInteger totalRequests; CloseableHttpClient httpClient; HttpGet httpGet; ExecutorService executorService; public CustomBenchMarker(String url, int concurrency, int total) { this.url = url; this.concurrency = concurrency; totalRequests = new AtomicInteger(total); List<Long> list = new LinkedList<Long>(); this.responseTimes = Collections.synchronizedList(list); executorService = Executors.newFixedThreadPool(concurrency); httpClient = HttpClients.custom().setMaxConnPerRoute(concurrency) .setConnectionReuseStrategy(new ConnectionReuseStrategy() { @Override public boolean keepAlive(HttpResponse response, HttpContext context) { return true; } }).build(); httpGet = new HttpGet(url); } public void startTest() throws Exception { for (int i = 0; i < concurrency; ++i) { executorService.execute(() -> { try { test(); } catch (Exception e) { e.printStackTrace(); } }); } executorService.awaitTermination(10, TimeUnit.SECONDS); System.out.println(responseTimes.size()); } public void report() { int requestCounts = responseTimes.size(); responseTimes.sort((a, b) -> a.compareTo(b)); Long p50 = responseTimes.get((int) (requestCounts * 0.5)); Long p95 = responseTimes.get((int) (requestCounts * 0.95)); Long p99 = responseTimes.get((int) (requestCounts * 0.99)); long avgResponseTime = 0; for (int i = 0; i < requestCounts; ++i) { avgResponseTime += responseTimes.get(i); } System.out.println(String.format("average response time: %d", avgResponseTime / requestCounts)); System.out.println(String.format("50%% response time: %d", p50)); System.out.println(String.format("95%% response time: %d", p95)); System.out.println(String.format("99%% response time: %d", p99)); } public void test() throws Exception { Long responseTime = 0l; Long taskStart; while (totalRequests.decrementAndGet() > 0) { taskStart = System.currentTimeMillis(); CloseableHttpResponse response = httpClient.execute(httpGet); response.close(); responseTime = System.currentTimeMillis() - taskStart; responseTimes.add(responseTime); } } public static void main(String[] args) throws Exception { CustomBenchMarker benchMarker = new CustomBenchMarker("https://www.baidu.com", 10, 100); benchMarker.startTest(); benchMarker.report(); }}
输出示例:
average response time: 5750% response time: 4495% response time: 18399% response time: 184
划线
评论
复制
发布于: 2020 年 11 月 09 日阅读数: 30
版权声明: 本文为 InfoQ 作者【文智】的原创文章。
原文链接:【http://xie.infoq.cn/article/e262c630fed40bde8598bd871】。未经作者许可,禁止转载。
文智
关注
还未添加个人签名 2018.11.29 加入
还未添加个人简介
评论