架构师训练营第七周 - 作业

用户头像
草原上的奔跑
关注
发布于: 2020 年 07 月 21 日
架构师训练营第七周-作业



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



响应时间

吞吐量

响应时间和吞吐量变化情况如上图

响应时间:初始时,基本无变化,到一定之后,响应时间随着并发数的增加,越来越大,到系统崩溃时,响应时间最大,且响应时间增长的速度也是加大的

吞吐量:先升高后降低,在系统达到负载安全点,吞吐量达到顶峰,然后降低,直到崩溃

吞吐量、响应时间、并发数三者之间的关系:

TPS = 并发数 * 1000 / 响应时间

原因

  1. 服务器在初始时,系统资源充足,满足请求所需要的资源,响应时间基本无变化,但随着并发数的增加,吞吐量也在提高

  2. 当系统资源有一种或多种达到瓶颈时,此时达到安全负载点,响应时间比初始时增大,但是因为并发数变动更大,所以吞吐量总体上时增大的

  3. 当并发数继续增大时,响应时间继续增长,增长势头超过了并发数的增长势头,所以吞吐量这时是下降的

  4. 到系统停止服务,响应时间达到最大,吞吐量也戛然而止



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



题解:对http://www.baidu.com做请求,有10个线程可供使用,总共100次

这次使用了springboot的RestTemplate做http客户端,使用http传参,在controller方法中发送请求,获取响应时长,并计算平均时长,以及95%时长。



  1. 客户端传输url,count,concurrent

  2. controller方法中根据concurrent创建fixed线城池

  3. 构建Callable任务放入线程池,并把Future放入List中

  4. 从List<Future>获取List<Long>,请求响应时间列表

  5. 从小到大排序响应时间列表,并计算平均值

  6. 返回结果到客户端



代码如下

controller

package com.zd.resttemplate.controller;
import com.zd.resttemplate.result.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
/**
* @author zhaodeng
* @date 2020/07/24 22:13
*/
@org.springframework.web.bind.annotation.RestController
public class RestController {
private final RestTemplate restTemplate;
@Autowired
public RestController(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@GetMapping("/request")
public Result request(@RequestParam("url") String url,
@RequestParam("count") Integer count,
@RequestParam("concurrent") Integer concurrent) {
ExecutorService executorService = Executors.newFixedThreadPool(concurrent);
List<Future<Long>> futures = new ArrayList<>(count);
restTemplate.getForObject(url, String.class);
for (int i = 0; i < count; i++) {
futures.add(executorService.submit(() -> {
long start = System.currentTimeMillis();
restTemplate.getForObject(url + "?t=" + System.nanoTime(), byte[].class);
return System.currentTimeMillis() - start;
}));
}
List<Long> durationList = futures.stream().map(f -> {
try {
return f.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return 0L;
}).sorted(Comparator.comparingLong(i -> i)).collect(Collectors.toList());
Result result = new Result();
result.setAverage(durationList.stream().mapToLong(l-> l).average().orElse(-1d));
result.setOrder95(durationList.get(94));
System.out.println(durationList);
return result;
}
}



Result:

package com.zd.resttemplate.result;
/**
* @author zhaodeng
* @date 2020/07/24 22:23
*/
public class Result {
private Double average;
private Long order95;
public Double getAverage() {
return average;
}
public void setAverage(Double average) {
this.average = average;
}
public Long getOrder95() {
return order95;
}
public void setOrder95(Long order95) {
this.order95 = order95;
}
@Override
public String toString() {
return "Result{" +
"average=" + average +
", order95=" + order95 +
'}';
}
}



RestTemplate:

package com.zd.resttemplate.config;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @author zhaodeng
* @date 2020/07/24 22:05
*/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}



10次的测试结果如下:

1:
{
"average": 16.07,
"order95": 74
}
2:
{
"average": 12.59,
"order95": 22
}
3:
{
"average": 11.44,
"order95": 24
}
4:
{
"average": 11.61,
"order95": 25
}
5:
{
"average": 9.08,
"order95": 22
}
6:
{
"average": 11.67,
"order95": 24
}
7:
{
"average": 11.54,
"order95": 23
}
8:
{
"average": 12.07,
"order95": 22
}
9:
{
"average": 10.06,
"order95": 26
}
10:
{
"average": 11.69,
"order95": 21
}

返回结果中,时间的单位为毫秒(ms)。

用户头像

草原上的奔跑

关注

喜欢简洁干净的代码 2018.05.04 加入

使用技术,实现业务。思考业务,创新技术。

评论

发布
暂无评论
架构师训练营第七周-作业