性能测试

用户头像
满山李子
关注
发布于: 2020 年 07 月 19 日
  1. 性能测试的时候, 随着并发压力的增加, 系统响应时间和吞吐量如何变化, 为什么

并发数: 应用系统能够同时处理的请求数码, 反映了系统的负载特性。

响应时间: 应用系统从发出请求开始到收到响应数据所需的世界; 响应时间, 直观的反映了系统的 "快慢" 。

吞吐量:单位时间内系统处理的请求的数量, 体现系统的处理能力;TPS(每秒事务数), HPS(每秒HTTP请求数),QPS(每秒查询次数)



先来看一下, 响应时间随并发用户数的变化

随着并发用户数的增加, 响应时间刚开始平缓线性增加的, 到c点,随着并发的增加响应时间指数级增加;c就是系统最大负载点;这是因为并发量再增加系统处理不过来了,待处理的任务会驻留在内存中, 且不断增加,这样就会不断增加对内存消耗;并发数量超过了系统最大的负载点,每一个任务分到时间CPU的时间片变少了,就需要更长处理时间;当并发数量达到d点时,整个系统卡死了, 等待执行完的任务不释放资源,正在执行的任务获得不到更多资源无法向下执行;



再说,吞吐量与并发数的关系

计算公式: QPS(TPS)= 并发数/平均响应时间

说明:

  • QPS(每秒查询次数)= 查询并发数 / 查询的平均响应时间

  • TPS(每秒事务数)= 事务并发数 / 事务的平均响应时间

如果只看分子好像吞吐量随着并发数增加而增加,但是随着并发数的增加到某个临界点后, 平均响应时间呈现指数级的增加。也就是说刚开始吞吐量随并发量的增加而增加, 到达某个临界点后,吞吐量随着并发量增加而下降,最后系统进入卡死状态吞吐量为0



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



import org.apache.hc.client5.http.fluent.Request;
import org.apache.hc.core5.http.HttpResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
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;
public class WebPressTest{
public static void main(String[] args){
WebPressTestUtils.testURL("https://www.baidu.com", 1000, 100);
// https://www.infoq.cn/: 并发数量100 请求数量: 1000 平均响应时间:1516.942ms %95响应时间: 4529.049999999998ms
// https://www.baidu.com: 并发数量100 请求数量: 1000 平均响应时间:196.409ms %95响应时间: 1534.05ms
}
}
class WebPressTestUtils{
public static void testURL(String url, int requestCount, int concurrent){
List<Long> responseTimeList = Collections.synchronizedList(new ArrayList<Long>());
ExecutorService es = Executors.newFixedThreadPool(concurrent);
AtomicInteger current_concurent = new AtomicInteger( 0);
for(int i=0; i<requestCount; i++){
es.execute(new WebPressTestRunner(url, current_concurent, responseTimeList));
}
es.shutdown();
try {
es.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
}
double responseTimeAvg = average(responseTimeList);
double responseTime95 = percentile(responseTimeList, 0.95);
System.out.print(url+": 并发数量"+concurrent+" 请求数量: "+requestCount +
" 平均响应时间:" + responseTimeAvg + "ms %95响应时间: " + responseTime95 + "ms");
}
public static double average(List<Long> list){
double total = 0.0;
for(long value : list){
total += value;
}
return total / list.size();
}
public static double percentile(List<Long> list,double p){
int n = list.size();
Collections.sort(list);
double px = p*(n-1);
int i = (int)java.lang.Math.floor(px);
double g = px - i;
if(g==0){
return list.get(0);
}else{
return (1 - g) * list.get(i) + g * list.get(i+1);
}
}
}
class WebPressTestRunner implements Runnable {
private String url;
private AtomicInteger current_concurrent;
private List<Long> responseTimeList;
public WebPressTestRunner(String url, AtomicInteger current_concurrent, List<Long> responseTimeList){
this.url = url;
this.current_concurrent = current_concurrent;
this.responseTimeList = responseTimeList;
}
public void run() {
try {
this.current_concurrent.incrementAndGet();
// System.out.println("当前并发数量"+ this.current_concurrent);
long start = System.currentTimeMillis();
HttpResponse response = Request.get(url).execute().returnResponse();
if(response.getCode() == 200) {
long end = System.currentTimeMillis();
long responseTime = end - start;
responseTimeList.add(responseTime);
}else{
System.out.println("响应失败");
}
this.current_concurrent.decrementAndGet();
} catch (IOException e) {
e.printStackTrace();
this.current_concurrent.decrementAndGet();
}
}
}



用户头像

满山李子

关注

还未添加个人签名 2018.09.18 加入

还未添加个人简介

评论 (1 条评论)

发布
用户头像
请添加‘极客大学架构师训练营“标签,便于分类
2020 年 07 月 21 日 10:59
回复
没有更多了
性能测试