架构师训练营第七周作业 - 性能测试

用户头像
sunnywhy
关注
发布于: 2020 年 07 月 22 日

作业一: 性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?

随着并发用户数的增加,响应时间的变化如上图所示。

在最佳运行区间1内,随着并发用户数的增加,响应时间只是缓的增加,因为在此区间内,系统有充分的资源(内存,CP,网络)可以使用。 吞吐量可以由如下公式推导:吞吐量=1000/响应时间ms * 并发量。 所以在最佳运行区间,由于响应时间并没有太多增加, 而并发量线性增长,所以吞吐量也是接近于线性增长。

在区间2,随着并发量的继续增加,响应时间也开始明显增加,但是增加的速度还是小于并发量的增加速度,所以根据吞吐量的公式,吞吐量还是继续增加的。c点上,并发量的增速跟响应时间的增速是相同的,所以在此时,系统吞吐量达到最大点。

在区间3,当越过c点后,响应时间的增速开始显著大于并发用户数的增速。因为此时系统内的资源利用率已经达到极限,线程开始阻塞,所以需要有线程开始等待其他线程完成才能开始执行。所以响应时间大大延长。当并发量继续增加时,越来越多的线程开始阻塞,最终在d点,系统无法响应而崩溃,此时的响应时间理论上是无限长。



作业二:用你熟悉的编程语言写一个 web 性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com。



使用apache httpclient创建一个简单的任务类,用于异步执行请求并返回响应时间:

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 java.util.concurrent.Callable;
public class HttpGetTask implements Callable<Long> {
private final String url;
public HttpGetTask(String url) {
this.url = url;
}
@Override
public Long call() throws Exception {
HttpGet request = new HttpGet(url);
long start = System.currentTimeMillis();
try (CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = httpClient.execute(request)) {
if(response.getEntity() != null){
long end = System.currentTimeMillis();
return end - start;
}
}
throw new RuntimeException("error happened when call the url");
}
}



创建一个主类,接收请求数,并发数和测试的url,根据请求数创建线程,通过Future汇总响应时间。

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.*;
public class LoadTestRunner {
private final ExecutorService executor;
private final int requestNumber;
private final String url;
public LoadTestRunner(int requestNumber, int currentNumber, String url) {
this.executor = Executors.newFixedThreadPool(currentNumber);
this.requestNumber = requestNumber;
this.url = url;
}
public void test() throws InterruptedException, ExecutionException {
List<Callable<Long>> requestList = new ArrayList<>();
for (int i = 0; i < requestNumber; i++) {
requestList.add(new HttpGetTask(url));
}
List<Future<Long>> futureList = executor.invokeAll(requestList);
List<Long> executeTimeList = new ArrayList<>();
Long totalTime = 0L;
for (Future<Long> longFuture : futureList) {
Long time = longFuture.get();
executeTimeList.add(time);
totalTime += time;
}
executeTimeList.sort(Comparator.naturalOrder());
long percentileIndex = Math.round(requestNumber * 0.95);
System.out.println("95% 响应时间: " + executeTimeList.get((int) percentileIndex) + "ms");
System.out.println("平均响应时间" + totalTime / requestNumber +"ms");
}
public static void main(String[] args) {
LoadTestRunner testRunner = new LoadTestRunner(100, 10, "http://www.google.ca");
try {
testRunner.test();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}



Main函数测试结果如下:

95% 响应时间: 447ms

平均响应时间122ms



发布于: 2020 年 07 月 22 日 阅读数: 7
用户头像

sunnywhy

关注

还未添加个人签名 2019.04.25 加入

还未添加个人简介

评论 (1 条评论)

发布
用户头像
请加“极客大学架构师训练营”标签,便于分类
2020 年 07 月 22 日 18:22
回复
没有更多了
架构师训练营第七周作业-性能测试