第七周作业

用户头像
晴空万里
关注
发布于: 2020 年 12 月 06 日



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



性能测试是一个不断对系统增加访问压力,以获得系统性能指标、最大负载能力、最大压力承受能力的过程。所谓的增加访问压力,在系统测试环境中,就是不断增加测试程序的并发请求数,一般来说,性能测试遵循图1的抛物线规律。



图1横轴表示消耗的系统资源(也可以认为是并发数,因为并发数越多,线程越多,消耗的资源也就越多),纵轴表示系统处理能力(吞吐量)。



在开始阶段,随着并发请求数目的增加,系统使用较少的资源就达到较好的处理能力(a~b段),这一段是网站的日常运行区间,网站的绝大部分访问负载压力都集中在这一段区间,被称作性能测试,测试目标是评估系统性能是否符合需求及设计目标;



随着压力持续增加,系统处理能力增加变缓,直到达到一个最大值(c点),这是系统的最大负载点,这一段被称作负载测试。测试目标是评估当系统因为突发事件超出日常访问压力的情况下,保证系统正常运行情况下能够承受的最大访问负载压力;



超过这个点之后,再增加压力,系统的处理能力反而下降,而资源消耗却更多,直到资源消耗达到极限(d点),这个点可以看作是系统崩溃点,超过这个点继续加大并发请求数目,系统不能再处理任何请求,这一段被称作压力测试,测试目标是评估可能导致系统崩溃的最大访问负载压力。



为什么有这样的一个曲线呢?

首先:a~b的时候,系统资源充足,并发数逐渐增多,小于CPU的核心数目,那么每一个请求都能很快被处理掉,而且CPU的资源利用率比较低,所以一开始的时候,并发数增加,TPS反倒增加得更快,曲线略微上扬。

然后达到b点;从此刻以后,再增加并发数目,CPU有效的核心就渐渐处理不过来线程数了,线程的切换变得更频繁,处理的响应相对就变慢了,因为线程切换、并发数增加本身对资源也在不断的消耗,那么留给处理计算的资源就会渐渐变少,此时呢,曲线略微下落,但整体还是增加的(b~c);到c点以后,最大负载点。

超过这个点以后,系统资源就被更多的并发数压垮了,系统无更多资源来处理计算,而非处理的消耗却更多,但是系统还是能够处理,只是处理数大大的下降,图形有个下挫,当到底d点以后,随着并发数持续的增加,终于将系统的资源耗尽,系统在资源切换、线程切换、从硬盘读取数据等各种操作上耗尽了资源,导致系统不能处理任务请求,系统挂掉了。

这就是这个曲线的来历。



图1

性能测试反应的是系统在实际生产环境中使用时,随着用户并发访问数量的增加,系统的处理能力。与性能曲线相对应的是用户访问的等待时间(系统响应时间),如下图所示:

图2

在日常运行区间,可以获得最好的用户响应时间,随时并发用户数的增加,响应延迟越来越大,直到系统崩溃,用户失去响应。



2、压测工具

新建一个SpringBoot项目 引入WebClient依赖 它是新的spring5推荐的http请求工具

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>



sendOne方法模拟10个线程并发请求,使用了CountDownLatch倒计数器,每10个线程,同时发起请求。

然后循环执行了100次。将相应结果保存起来,计算。

不过WebClient请求调用我直接判断了返回值,因为不知道怎么去解析HTML响应结果,研究了一下,无疾而终。



参考资料:

https://blog.csdn.net/wgq3773/article/details/81052358

https://howtodoinjava.com/spring-webflux/webclient-get-post-example/#get





具体代码:

package kd.autops.service.impl;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* @author chenhao
* @date 2020/12/06
*/
public class WebTest {
private void test(String uri) {
// 建立ExecutorService线程池,threadNum个线程可以同时访问
int threadNumber = 10;
int requestNumber = 100;
// 计数器
AtomicInteger atomicInteger = new AtomicInteger(1);
// 线程池 测试使用
ExecutorService exec = Executors.newFixedThreadPool(threadNumber);
// 保存结果
ConcurrentHashMap<Integer, Long> result = new ConcurrentHashMap<>(1000);
// 执行100次并发
for (int i = 1; i <= requestNumber; i++) {
// 10个线程并发执行1次
ConcurrentHashMap<Integer, Long> sendOne = sendOne(uri, atomicInteger, exec);
// 保存结果
result.putAll(sendOne);
}
// 累计时间
long sum = 0;
for (Long value : result.values()) {
sum += value;
}
// 平均时间
double avg = sum * 1.0 / result.size() * 1.0;
// 排序获取第95%的记录
List<Long> collect = result.values().stream().sorted().collect(Collectors.toList());
System.out.println(String.format("请求URL:%s,请求总次数:%d,并发数:%d", uri, requestNumber * threadNumber, threadNumber));
System.out.println(String.format("平均响应时间:%f 毫秒,95%%响应时间:%d 毫秒", avg, collect.get(949)));
}
private ConcurrentHashMap<Integer, Long> sendOne(String uri, AtomicInteger atomicInteger, ExecutorService exec) {
// 模拟clientNum个客户端访问
final CountDownLatch doneSignal = new CountDownLatch(10);
ConcurrentHashMap<Integer, Long> result = new ConcurrentHashMap<>(10);
// 10个线程发1次
for (int i = 0; i < 10; i++) {
Runnable runnable = () -> {
long beginMillis = System.currentTimeMillis();
WebClient.create()
.get()
//多个参数也可以直接放到map中,参数名与placeholder对应上即可
.uri(uri)
.retrieve()
.onStatus(HttpStatus.FOUND::equals, clientResponse -> Mono.empty());
long endMillis = System.currentTimeMillis();
long r = endMillis - beginMillis;
result.put(atomicInteger.getAndIncrement(), r);
doneSignal.countDown();
};
exec.execute(runnable);
}
try {
doneSignal.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
return result;
}
public static void main(String[] args) {
String uri = "http://www.baidu.com";
new WebTest().test(uri);
}
}



用户头像

晴空万里

关注

还未添加个人签名 2018.07.18 加入

还未添加个人简介

评论

发布
暂无评论
第七周作业