【架构师训练营第 1 期 07 周】 作业

用户头像
Bear在挨踢
关注
发布于: 2020 年 11 月 08 日

【架构师训练营第 1 期 07 周】 作业



作业题目:

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

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



解答:

1.

响应时间:系统接收到请求到最终返回结果的总时间,也是用户感受到的时间。

吞吐量:指单位时间内系统处理的请求数量,体现软件系统的处理能力。



上图中左边是并发测试是吞吐量的趋势图,右边是响应时间的趋势图。

其中

请求量:a>b>c

第一阶段(a->b):是性能测试阶段,压力在系统轻承受的范围内;

第二阶段(b->c):是负载测试阶段,系统压力达到比较高的情况,准备达到瓶颈;

第三阶段(c->d):系统达到瓶颈,无法及时响应接口。



在第一段里面,处于系统可以轻松承受的范围,所以吞吐量线性增长,响应时间还是很快;

第二阶段,访问量上升导致系统有一定压力,所以吞吐量增长放缓,响应时间开始延长。

第三阶段,访问量上升达到系统瓶颈位置,由于处理不过来,导致后面的请求阻塞了,而且过多的请求也会占用系统资源,所以吞吐量会开始下降,处理时间也会延长。最严重的情况是系统宕机,无法接收和处理请求了。



2.

网络请求方法


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;

public class HttpUtils {

// 封装Get请求
public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = param == null ? url : url + "?" + param;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection connection = realUrl.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)");
// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> map = connection.getHeaderFields();
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
connection.getInputStream(),"utf-8"));//防止乱码
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
}



测试方法


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class Test07 {

// 请求总数
public static int clientTotal = 100;

// 同时并发执行的线程数
public static int threadTotal = 10;

// 请求地址
public static String url = "http://www.baidu.com";

// 所有处理时间
public static List<Long> times = new ArrayList<>();

public static void main(String[] args) throws Exception {

ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
long starTime = System.currentTimeMillis();
//这里实现http请求
HttpUtils.sendGet(url, null);
//结束时间
long endTime = System.currentTimeMillis();
add(endTime - starTime);
semaphore.release();
} catch (Exception e) {
e.printStackTrace();
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
count(times, clientTotal);
}

private static void add(long time) {
//System.out.println(time);
times.add(time);
}

private static void count(List<Long> times, int client) {
Long avg = 0L;
for (Long l : times) {
avg += l;
}
Collections.sort(times);
System.out.println("平均响应时间:"+ avg/client +"ms,95%响应时间在:"+times.get((int)(0.95*client)-1)+"ms以内。");
}

}



结果



总结:

其实前面的请求耗时会比较长,估计是因为初次建立链接,所以比较慢。

发布于: 2020 年 11 月 08 日阅读数: 27
用户头像

Bear在挨踢

关注

还未添加个人签名 2019.02.16 加入

还未添加个人简介

评论

发布
暂无评论
【架构师训练营第 1 期 07 周】 作业