架构师培训 -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次平均响应时间:613ms95%响应时间<=:768ms最小响应时间:569ms最大响应时间:783ms20并发,执行1次平均响应时间:1824ms95%响应时间<=:3758ms最小响应时间:518ms最大响应时间:6618ms30并发,执行1次平均响应时间:1363ms95%响应时间<=:3655ms最小响应时间:557ms最大响应时间:9711ms100并发,执行1次平均响应时间:1230ms95%响应时间<=:3570ms最小响应时间:723ms最大响应时间:5351ms
10并发,执行3次平均响应时间:1665ms95%响应时间<=:3576ms最小响应时间:526ms最大响应时间:9529ms20并发,执行3次平均响应时间:2047ms95%响应时间<=:9713ms最小响应时间:742ms最大响应时间:19567ms30并发,执行3次平均响应时间:1559ms95%响应时间<=:3838ms最小响应时间:702ms最大响应时间:9724ms100并发,执行3次平均响应时间:3895ms95%响应时间<=: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]; } }
划线
评论
复制
发布于: 2020 年 07 月 22 日阅读数: 64
刘敏
关注
还未添加个人签名 2018.04.25 加入
还未添加个人简介
评论