写点什么

架构师训练营第 1 期第 7 周作业

用户头像
业哥
关注
发布于: 2020 年 11 月 03 日
架构师训练营第 1 期第 7 周作业

问题:

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

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



解1:

图1

图2



如上图1为性能压测的时候随着并发压力的增加,系统响应吞吐量的变化曲线,解释如下:

  • 系统刚开始资源充足,随着并发的增大,系统的吞吐量(TPS)线性增大,见图种a-b段;

  • 当并发增大到一定大小,系统资源消耗增大,不足以支撑系统的吞吐量与并发数呈线性增长的态势,支撑系统的吞吐量增长变缓,见图b-c段;

  • 当并发继续增大,系统资源消耗慢慢耗尽,此时系统吞吐量不增反降,直到系统资料耗尽,到系统奔溃点后,系统吞吐量为0. 这个阶段曲线见图c-d段;



如上图2为性能压测的时候随着并发压力的增加,系统响应时间的变化曲线,解释如下:

  • 系统刚开始资源充足,随着并发的增大,系统的响应时间比较块而且稳定,见图种a-b段;

  • 当并发增大到一定大小,系统资源消耗增大,不足以支撑系统的吞吐量与并发数呈线性增长的态势,这个阶段系统响应时间随着并发的增大逐渐增大,见图b-c段;

  • 当并发继续增大,系统资源消耗慢慢耗尽,此时系统吞吐量不增反降,响应时间也急剧增大,直到系统资料耗尽,到系统奔溃点后,系统吞吐量为0,系统没有了响应。 这个阶段曲线见图c-d段;



解2:

本题用java来实现

程序实现用3个类来实现本功能:

  1. TestResult.java:单个线程执行压测后测试结果类

  2. LoadThread.java:压测线程类,实现Runable接口

  3. MyLoadTestMain:压测主程序类,程序入口;



代码如下:

package org.yege.algorithm.loadtest;
/**
* 测试结果类
*/
public class TestResult {
private boolean isSuccess;//是否成功,true;成功,false:失败
private long finishTime;//成功完成时间,单位ms
public boolean isSuccess() {
return isSuccess;
}
public void setSuccess(boolean success) {
isSuccess = success;
}
public long getFinishTime() {
return finishTime;
}
public void setFinishTime(long finishTime) {
this.finishTime = finishTime;
}
@Override
public String toString() {
return "TestResult{" +
"isSuccess=" + isSuccess +
", finishTime=" + finishTime +
'}';
}
}



package org.yege.algorithm.loadtest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
/**
* 并发压测线程类
*/
public class LoadThread implements Runnable{
private List<TestResult> testResults;//测试结果集
private String loadUrl;//测试url
public LoadThread(List<TestResult> testResults, String loadUrl) {
this.testResults = testResults;
this.loadUrl = loadUrl;
}
public void run() {
TestResult testResult=new TestResult();
long startTime=System.currentTimeMillis();
try {
URL url = new URL(loadUrl);
URLConnection urlConnection = url.openConnection();
HttpURLConnection connection = (HttpURLConnection) urlConnection;
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String urlString = "";
String current;
while((current = in.readLine()) != null) {
urlString += current;
}
testResult.setSuccess(true);
}catch(IOException e) {
testResult.setSuccess(false);
}
long endTime=System.currentTimeMillis();
long cha=endTime-startTime;
testResult.setFinishTime(cha);
testResults.add(testResult);
//System.out.println(testResult.toString());
}
public List<TestResult> getTestResults() {
return testResults;
}
public void setTestResults(List<TestResult> testResults) {
this.testResults = testResults;
}
public String getLoadUrl() {
return loadUrl;
}
public void setLoadUrl(String loadUrl) {
this.loadUrl = loadUrl;
}
}



package org.yege.algorithm.loadtest;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @author 业哥
* java版Web性能压测工具
* 需求:
* 1.用java编程语言写一个 Web 性能压测工具,
* 2.输入参数:URL,请求总次数,并发数。
* 3.输出参数:平均响应时间,95% 响应时间。
* 4.用这个测试工具以 10 并发、100 次请求压测
*
*
*/
public class MyLoadTestMain {
/**
* @param args
* args[0]:参数1:并发数
* args[1]:参数2:总请求数
* args[2]:参数3:待压测url链接
*/
public static void main(String[] args) {
if(args==null||args.length!=3){
System.err.println("参数为空,或者参数个数小于3");
return;
}
int n1;//args[0]:参数1:并发数
int n2;//args[1]:参数2:总请求数
String loadUrl=args[2];//args[2]:待压测url链接
try {
n1=Integer.parseInt(args[0]);
n2=Integer.parseInt(args[1]);
}catch (Exception ex){
System.err.println(ex.getMessage());
return;
}
if(n2<n1){
System.err.println("参数【总请求数】小于了参数【并发数】");
return;
}
//计算需要n1个并发请求的次数
int count=n2/n1;//eg:n2=100,n1=10,count=10
List<TestResult> testResults=new ArrayList<TestResult>();
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
//执行n2次总请求【以count次并发请求(每次n1个并发请求)】
for(int i=0;i<count;i++){
List<TestResult> subTestResults=new ArrayList<TestResult>();
for(int j=0;j<n1;j++){
Runnable runnable=new LoadThread(subTestResults,loadUrl);
runnable.run();
}
while (true){
if(subTestResults.size()==n1){
testResults.addAll(subTestResults);
System.out.println(sdf.format(new Date())+":已经完成"+testResults.size()+"个请求");
break;
}
}
}
//计算平均响应时间
long totalTime=0;
long successRequet=0;
for(TestResult testResult:testResults){
if(testResult.isSuccess()){
successRequet++;
totalTime+=testResult.getFinishTime();
}
}
double t=totalTime;
double s=successRequet;
double perQuestTime =t/s;
//计算95%响应时间
Collections.sort(testResults, new Comparator<TestResult>() {
public int compare(TestResult o1, TestResult o2) {
if(o1.getFinishTime()>o2.getFinishTime()){return 1;}
if(o1.getFinishTime()==o2.getFinishTime()){return 0;}
if(o1.getFinishTime()<o2.getFinishTime()){return -1;}
return -1;
}
});
int off= (int)(testResults.size()*0.95);
long per95QuestTime=testResults.get(off).getFinishTime();
System.out.println("【本次测试】单次并发数:"+n1+",总请求数:"+n2+",测试url:"+loadUrl+"");
System.out.println("【本次测试】平均响应时间:"+perQuestTime+"ms,95% 响应时间:"+per95QuestTime+"ms");
}
}



测试结果截图1:



测试结果截图2:



测试结果截图3:



测试结果截图4:



用户头像

业哥

关注

架构即未来! 2018.02.19 加入

还未添加个人简介

评论

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