架构师训练营 1 期 - 第七周作业(vaik)
发布于: 2020 年 11 月 08 日
性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?
答:性能压则的时候,随并并压力的增加,系统响应时间开始水平线,然后线性上升,最后达到性能极限时,无响应或会响应超时,而吞吐量则是一个抛物性形状,先升高,达到最高点,相当于系统性能极限,然后开始下降,最终到系统崩溃。
用你熟悉的编程语言写一个 Web 性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com。
工具由五个类组成
main 方法入口类:SimplePressureTestDemo
任务类:Task
任务结果类:TaskResult
任务线程执行类:TaskRunner
请求发送类:HttpRequestUtil
添加两个 Maven 类库引用
org.apache.httpcomponents.httpclient:4.5.12
org.projectlombok.lombok:1.18.12
命令行传入三个参数: url concurrentNumber requestNumber
执行结果:
package com.vaik.pressuretest;
import lombok.Data;
import java.util.List;
@Data
public class Task {
//请求的URL
private String url;
//开启线程数
private int threadNumber;
//总请求数量
private int requestNumber;
//已完成请求数
private int completedNumber;
//请求结果集
private List<TaskResult> results;
}
复制代码
package com.vaik.pressuretest;
import lombok.Data;
@Data
public class TaskResult {
//开始时间戳
private long startTime;
//结束时间戳
private long endTime;
//消耗时间长
private long consumeTime;
//任务号
private long taskNumber;
//执行任务线程
private String runThreadName;
//执行结果
private String msg;
}
复制代码
package com.vaik.pressuretest;
public class TaskRunner implements Runnable {
private static final Object obj = new Object();
private Task task;
public TaskRunner(Task task){
this.task = task;
}
@Override
public void run() {
while (!isEnd()){
synchronized (obj){
task.setCompletedNumber(task.getCompletedNumber()+1);
//System.out.println("setCompletedNumber "+task.getCompletedNumber());
}
TaskResult taskResult = new TaskResult();
long startTime = System.currentTimeMillis();
taskResult.setStartTime(startTime);
//System.out.println("start HttpRequestUtil");
String res = HttpRequestUtil.get(task.getUrl());
//System.out.println("HttpRequestUtil response:" + res);
if(res.isEmpty()){
taskResult.setMsg(Thread.currentThread().getName()+" has exception, taskNumber"+(task.getCompletedNumber()+1));
}else{
taskResult.setMsg(Thread.currentThread().getName()+ " success taskNumber:"+(task.getCompletedNumber()+1));
}
long endTime = System.currentTimeMillis();
taskResult.setEndTime(endTime);
taskResult.setConsumeTime(endTime-startTime);
taskResult.setTaskNumber(task.getCompletedNumber()+1);
taskResult.setRunThreadName(Thread.currentThread().getName());
task.getResults().add(taskResult);
//System.out.println("end HttpRequestUtil");
}
}
private boolean isEnd(){
synchronized (obj) {
boolean bl = false;
if (task.getCompletedNumber() >= task.getRequestNumber()) {
bl = true;
}
return bl;
}
}
}
复制代码
package com.vaik.pressuretest;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class SimplePressureTestDemo {
public static void main(String[] args) throws InterruptedException {
if(args.length == 3) {
String url = args[0];
int threadNumber = Integer.parseInt(args[1]);
int requestNumber = Integer.parseInt(args[2]);
com.vaik.pressuretest.Task task = new com.vaik.pressuretest.Task();
task.setUrl(url);
task.setThreadNumber(threadNumber);
task.setRequestNumber(requestNumber);
task.setCompletedNumber(0);
List<TaskResult> list = new ArrayList<>();
task.setResults(list);
executeTask(task);
while(task.getCompletedNumber()<task.getRequestNumber()){
Thread.sleep(1000);
printResult(task);
}
}else{
System.out.println("参数个数不正确,正确格式 url concurrentNumber requestNumber");
}
}
public static void executeTask(Task task){
System.out.println("Start executeTask");
for(int i =0;i<task.getThreadNumber();i++){
TaskRunner taskRunner = new TaskRunner(task);
Thread thread = new Thread(taskRunner);
thread.setName("Thread#"+i);
thread.start();
}
}
public static void printResult(Task task){
List<TaskResult> results = task.getResults();
if(results.size()>0) {
results.sort(Comparator.comparing(TaskResult::getConsumeTime));
double avg = results.stream().mapToDouble(TaskResult::getConsumeTime).average().getAsDouble();
System.out.println("总需发送请求:" + task.getRequestNumber() + " 实际完成请求:" + task.getCompletedNumber());
System.out.println("平均响应时间:" + avg+"毫秒");
if (results.size() > 95)
System.out.println("95%响应时间:" + results.get(95).getConsumeTime()+"毫秒");
}
}
}
复制代码
package com.vaik.pressuretest;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
/**
* @author wanghang
* @Description
* @date: 2018/04/07 17:49
*/
public class HttpRequestUtil {
private static CloseableHttpClient httpClient;
static {
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(100);
cm.setDefaultMaxPerRoute(20);
cm.setDefaultMaxPerRoute(50);
httpClient = HttpClients.custom().setConnectionManager(cm).build();
}
public static String get(String url) {
CloseableHttpResponse response = null;
BufferedReader in = null;
String result = "";
try {
HttpGet httpGet = new HttpGet(url);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();
httpGet.setConfig(requestConfig);
httpGet.setConfig(requestConfig);
httpGet.addHeader("Content-type", "application/json; charset=utf-8");
httpGet.setHeader("Accept", "application/json");
response = httpClient.execute(httpGet);
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
result = sb.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != response) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
public static String post(String url, String jsonString) {
CloseableHttpResponse response = null;
BufferedReader in = null;
String result = "";
try {
HttpPost httpPost = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();
httpPost.setConfig(requestConfig);
httpPost.setConfig(requestConfig);
httpPost.addHeader("Content-type", "application/json; charset=utf-8");
httpPost.setHeader("Accept", "application/json");
httpPost.setEntity(new StringEntity(jsonString, Charset.forName("UTF-8")));
response = httpClient.execute(httpPost);
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
result = sb.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != response) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
}
复制代码
划线
评论
复制
发布于: 2020 年 11 月 08 日阅读数: 37
行之
关注
还未添加个人签名 2018.09.18 加入
还未添加个人简介
评论