第七周作业

用户头像
changtai
关注
发布于: 2020 年 07 月 20 日



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

性能测试的几个阶段:性能测试(性能预期)、负载测试(最大负载)、压力测试(崩溃点)、稳定性测试(稳定运行)



  1. 在系统测试阶段,系统资源充裕,随着并发的增加,响应时间平稳,系统的吞吐量快速增加

  2. 在负载测试阶段,随着并发的压力增加,系统部分资源已经达极限,响应时间开始变长,

系统的吞吐量基本达到极限

  1. 在压力测试阶段,对超负载的系统继续增加并发,系统开始崩溃,响应时间急速增加直到完全失去响应,系统负载也快速下降







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

代码如下:

/**
* 请求
* @author zhaoct
* @date 2020-07-20 9:25
*/
public class Request {
/**
* 请求URL
*/
private String url;
/**
* 请求总次数
*/
private Integer requests;
/**
* 请求并发数
*/
private Integer concurrency;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Integer getRequests() {
return requests;
}
public void setRequests(Integer requests) {
this.requests = requests;
}
public Integer getConcurrency() {
return concurrency;
}
public void setConcurrency(Integer concurrency) {
this.concurrency = concurrency;
}
}



/**
* 执行结果
*
* @author zhaoct
* @date 2020-07-20 9:33
*/
public class Result implements Comparable<Result> {
private Long startTime;
private Long endTime;
private Long executeTime;
private int code;
private Boolean isError;
public Long getStartTime() {
return startTime;
}
public void setStartTime(Long startTime) {
this.startTime = startTime;
}
public Long getEndTime() {
return endTime;
}
public void setEndTime(Long endTime) {
this.endTime = endTime;
}
public Long getExecuteTime() {
return this.endTime - this.startTime;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public Boolean getError() {
return "200".equals(code);
}
@Override
public int compareTo(Result result) {
if(this.getExecuteTime() > result.getExecuteTime()) {
return 1;
}else if(this.getExecuteTime() < result.getExecuteTime()) {
return -1;
}else{
return 0;
}
}
}



/**
* http工具类
* @author zhaoct
* @date 2020-07-20 9:25
*/
public class HttpUtil {
/**
* get 请求
* @param url
* @return http response code
* @throws Exception
*/
public static int doGet(String url) throws Exception{
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
try (CloseableHttpResponse response = httpclient.execute(httpGet)) {
//HttpEntity entity = response.getEntity();
//EntityUtils.consume(entity);
return response.getCode();
}
}
/**
* post 请求
* @param url
* @param paramList
* @return http response code
* @throws Exception
*/
public static int doPost(String url, List<NameValuePair> paramList) throws Exception{
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(paramList));
try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
//HttpEntity entity = response.getEntity();
//EntityUtils.consume(entity);
return response.getCode();
}
}
}



/**
* 模拟请求类
* @author zhaoct
* @date 2020-07-20 9:25
*/
public class Engine {
/**
* 请求
*/
private Request request = null;
/**
* 所有线程都准备好之后,再发起请求,防止线程启动时间带来误差
*/
private CountDownLatch startCountDownLatch = null;
/**
* 等待所有线程执行完成后返回结果
*/
private CountDownLatch endCountDownLatch = null;
public Engine(Request request){
this.request = request;
startCountDownLatch = new CountDownLatch(request.getConcurrency());
endCountDownLatch = new CountDownLatch(request.getConcurrency());
}
public List<Result> execute(){
List<Result> list = Collections.synchronizedList(new ArrayList<>());
for(int i=0; i<request.getConcurrency(); i++){
//线程只需要执行一次任务,不需要创建线程池
new Thread(
() -> {
startCountDownLatch.countDown();
try {
//等所有线程都启动了在执行,模拟并发
startCountDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int j=0; j<request.getRequests(); j++){
int code = 0;
long startTime = 0;
long endTime = 0;
try {
startTime = System.currentTimeMillis();
code = HttpUtil.doGet(request.getUrl());
endTime = System.currentTimeMillis();
} catch (Exception e) {
e.printStackTrace();
}finally {
Result result = new Result();
result.setCode(code);
result.setStartTime(startTime);
result.setEndTime(endTime);
list.add(result);
}
}
endCountDownLatch.countDown();
}
).start();
}
//所有线程都执行完了返回结果
try {
endCountDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
return list;
}
}



/**
* 统计数据类
* @author zhaoct
* @date 2020-07-20 9:25
*/
public class Statistics {
private List<Result> list = null;
public Statistics(List<Result> list){
this.list = list;
}
public long getAvgRT(){
long sumRT = 0;
for(Result result : list){
sumRT += result.getExecuteTime();
}
return sumRT / list.size();
}
public long get95PRT(){
//排序
Collections.sort(list);
//95分位值
return list.get((int)(list.size() * 95 / 100) - 1).getExecuteTime();
}
}



/**
* 启动类
* @author zhaoct
* @date 2020-07-20 9:25
*/
public class Main {
/**
* 启动方法
* @param args
* -n 即requests,用于指定压力测试总共的执行次数
* -c 即concurrency,用于指定的并发数
*/
public static void main(String[] args) {
Request request = new Request();
request.setUrl(args[args.length-1]);
for(int i=0; i<args.length; i++){
if("-n".equals(args[i])){
request.setRequests(Integer.parseInt(args[i+1]));
}else if("-c".equals(args[i])){
request.setConcurrency(Integer.parseInt(args[i+1]));
}
}
Engine engine = new Engine(request);
List<Result> list = engine.execute();
Statistics statistics = new Statistics(list);
System.out.println("平均响应时间:" + statistics.getAvgRT() + " ms ");
System.out.println("95% 响应时间:" + statistics.get95PRT() + " ms ");
}
}



执行结果:

[root@VM_17_65_centos zhaoct]# java -jar performance-test-tool-1.0-SNAPSHOT-jar-with-dependencies.jar -n 100 -c 10 http://www.baidu.com



平均响应时间:36 ms

95% 响应时间:38 ms



用户头像

changtai

关注

还未添加个人签名 2018.04.30 加入

还未添加个人简介

评论

发布
暂无评论
第七周作业