写点什么

架构师培训 -07 性能测试与性能优化

用户头像
刘敏
关注
发布于: 2020 年 07 月 22 日



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



1.在资源(CPU,内存,网络等)还充足的情况下,并发数增加系统响应时间不会有什么变化,吞吐量会增加。

原因:在资源充足的情况下,增加并发量,并不会影响造成资源争抢的问题。

2.当资源(CPU,内存,网络等)不够的情况下,并发数增加系统响应时间会变长,吞吐量会变小,直到系统崩溃。

原因:当资源不够的情况下,就存在资源争抢的问题,抢不到资源的需要进行等待。当等待的任务数不断增加的时候,网络,内存资源等都会慢慢被耗尽,CPU上下文切换开销不断增加,导致系统处理能力慢慢下降直到崩溃。







2.编写web性能测试代码

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

2.1测试结果

对极客时间首页(https://time.geekbang.org/)进行压测

10并发,执行1次
平均响应时间:613ms
95%响应时间<=:768ms
最小响应时间:569ms
最大响应时间:783ms

20并发,执行1次
平均响应时间:1824ms
95%响应时间<=:3758ms
最小响应时间:518ms
最大响应时间:6618ms

30并发,执行1次
平均响应时间:1363ms
95%响应时间<=:3655ms
最小响应时间:557ms
最大响应时间:9711ms

100并发,执行1次
平均响应时间:1230ms
95%响应时间<=:3570ms
最小响应时间:723ms
最大响应时间:5351ms



10并发,执行3次
平均响应时间:1665ms
95%响应时间<=:3576ms
最小响应时间:526ms
最大响应时间:9529ms

20并发,执行3次
平均响应时间:2047ms
95%响应时间<=:9713ms
最小响应时间:742ms
最大响应时间:19567ms

30并发,执行3次
平均响应时间:1559ms
95%响应时间<=:3838ms
最小响应时间:702ms
最大响应时间:9724ms

100并发,执行3次
平均响应时间:3895ms
95%响应时间<=:10139ms
最小响应时间:1459ms
最大响应时间:19991ms

2.2类图



2.3代码

Demo代码

package com.lm.test;

/**
* @author lm
* @description 测试
* @date 2020/7/22 15:26
*/
public class DemoTest {
public static void main(String[] args) {
String url = "https://time.geekbang.org/";
HttpPerformanceTest httpPerformanceTest = new HttpPerformanceTest(url,null);
SuitePerformanceTest suitePerformanceTest = new SuitePerformanceTest(100,1,httpPerformanceTest);
suitePerformanceTest.test();
}
}


测试接口

package com.lm.test;

/**
* @author lm
* @description 压力测试接口
* @date 2020/7/22 13:41
*/
public interface PerformanceTest {
Result test();
}


http测试实现

package com.lm.test;

import com.lm.test.util.HttpUtil;
import okhttp3.Response;

import java.io.IOException;
import java.util.Map;

/**
* @author lm
* @description http压测
* @date 2020/7/22 13:25
*/
public class HttpPerformanceTest implements PerformanceTest {

private String url;
private Map<String,Object> params;

public HttpPerformanceTest(String url,Map<String,Object> params) {
this.url = url;
this.params = params;
}

public Result test() {
long startTime = System.currentTimeMillis();
boolean result = false;
try {
Response response = HttpUtil.get(url,params);
if(response.isSuccessful()) {
result = true;
}
} catch (IOException e) {
}
long costTime = System.currentTimeMillis() - startTime;

return new Result(costTime,result);

}
}


压测类

package com.lm.test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;

/**
* @author lm
* @description
* @date 2020/7/22 14:18
*/
public class SuitePerformanceTest implements PerformanceTest {
/**
* 并发数
*/
private int number;
/**
* 执行次数
*/
private int repeat;

/**
* 结果集合
*/
private List<Result> resultList;


private PerformanceTest performanceTest;
private ExecutorService executor;

public SuitePerformanceTest(int number, int repeat, PerformanceTest performanceTest) {
this.number = number;
this.repeat = repeat;
this.performanceTest = performanceTest;
executor = Executors.newCachedThreadPool();
resultList = new ArrayList<Result>(repeat * number);
}

public Result test() {
CyclicBarrier cyclicBarrier = getCyclicBarrier();
for (int i = 0; i < repeat; i++) {
for (int j = 0; j < number; j++) {
executor.execute(new Executer(cyclicBarrier));
}
}
executor.shutdown();
try {
executor.awaitTermination(Integer.MAX_VALUE,TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(resultList.size()==repeat*number);
resultFormat();
return null;
}

public void resultFormat() {
long avgCostTime = avgCostTime();

Collections.sort(resultList);
int index = (repeat * number * 95) / 100;
long costTime95 = resultList.get(index - 1).getCostTime();

StringBuffer sb = new StringBuffer();
sb.append(number + "并发,");
sb.append("执行" + repeat + "次");
System.out.println(sb.toString());
System.out.println("平均响应时间:" + avgCostTime + "ms");
System.out.println("95%响应时间<=:" + costTime95 + "ms");
System.out.println("最小响应时间:" + resultList.get(0).getCostTime()+ "ms");
System.out.println("最大响应时间:" + resultList.get(repeat*number-1).getCostTime() + "ms");
}

private long avgCostTime() {
long totoal = 0;
for (Result result : resultList) {
totoal += result.getCostTime();
}
return totoal / (resultList.size());
}

private CyclicBarrier getCyclicBarrier() {
return new CyclicBarrier(number);
}

private synchronized void addResult(Result result) {
resultList.add(result);
}


private class Executer implements Runnable {
private CyclicBarrier cyclicBarrier;

public Executer(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}

public void run() {
try {
System.out.println(Thread.currentThread().getName() + " 等待");

cyclicBarrier.await();
System.out.println(Thread.currentThread().getName() + " 开始执行");
Result result = performanceTest.test();
addResult(result);
// cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}

结果类

package com.lm.test;

/**
* @author lm
* @description 单次执行结果
* @date 2020/7/22 17:12
*/
public class Result implements Comparable<Result>{
/**
* 耗时 ms
*/
private long costTime;

/**
* 请求结果 是否成功。
*/
private boolean result;

public Result(long costTime, boolean result) {
this.costTime = costTime;
this.result = result;
}

public long getCostTime() {
return costTime;
}

public void setCostTime(long costTime) {
this.costTime = costTime;
}

public boolean isResult() {
return result;
}

public void setResult(boolean result) {
this.result = result;
}

@Override
public String toString() {
return "Result{" +
"costTime=" + costTime +
", result=" + result +
'}';
}

public int compareTo(Result result) {
if(this.costTime > result.getCostTime()) {
return 1;
} else if(this.costTime > result.getCostTime()) {
return -1;
}
return 0;
}
}


http工具类

package com.lm.test.util;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

import javax.net.ssl.*;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
* @author lm
* @description http请求工具类
* @date 2020/7/22 12:20
*/
public class HttpUtil {
private static OkHttpClient httpClient;

static {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.readTimeout(5, TimeUnit.SECONDS);
builder.connectTimeout(3, TimeUnit.SECONDS);
builder.readTimeout(10, TimeUnit.SECONDS);

//支持https
builder.sslSocketFactory(createSSLSocketFactory());
builder.hostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession sslSession) {
return true;
}
});

httpClient = builder.build();

}


public static Response get(String url, Map<String, Object> params) throws IOException {
if (params != null) {
url = builderGetUrl(url, params);
}
Request request = new Request.Builder()
.url(url)
.build();
Response response = httpClient.newCall(request).execute();
return response;
}

public static String post(String url,Map<String,Object> params) {
//ToDo
return null;
}


private static String builderGetUrl(String url, Map<String, Object> params) {
StringBuffer sb = new StringBuffer(url + "?");
for(Map.Entry<String,Object> entry : params.entrySet()) {
if (entry.getValue() != null) {
sb.append("&");
sb.append(entry.getKey());
sb.append("=");
sb.append(entry.getValue());
}
}
url = sb.toString().replaceFirst("&", "");
return url;
}


public static SSLSocketFactory createSSLSocketFactory() {
SSLSocketFactory ssfFactory = null;
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, new TrustManager[]{new TrustAllCerts()}, new SecureRandom());
ssfFactory = sc.getSocketFactory();
} catch (Exception e) {
}
return ssfFactory;
}


}


package com.lm.test.util;

import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

class TrustAllCerts implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}



用户头像

刘敏

关注

还未添加个人签名 2018.04.25 加入

还未添加个人简介

评论

发布
暂无评论
架构师培训 -07 性能测试与性能优化