写点什么

架构师训练营 1 期 - 第七周 - 性能优化 1

用户头像
三板斧
关注
发布于: 2020 年 11 月 08 日

问题:

  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 来实现

package test;
public class TestResult implements Comparable<TestResult>{ private String threadName; private boolean success; private long time;
public String getThreadName() { return threadName; }
public void setThreadName(String threadName) { this.threadName = threadName; }

public boolean isSuccess() { return success; }
public void setSuccess(boolean success) { this.success = success; }
public long getTime() { return time; }
public void setTime(long time) { this.time = time; }
@Override public String toString() { return "TestResult [threadName=" + threadName + ", success=" + success + ", time=" + time + "]"; }
@Override public int compareTo(TestResult o) { Long t = this.getTime() - o.getTime(); return t.intValue() ; } }

复制代码


package test;
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.concurrent.Callable;import test.TestResult;
public class LoadThread implements Callable<TestResult>{ private String threadName; private String loadUrl; public LoadThread(String threadName,String loadUrl) { this.threadName = threadName; this.loadUrl = loadUrl;
}

@Override public TestResult call() throws Exception { 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 time=endTime-startTime; testResult.setTime(time); testResult.setThreadName(threadName); return testResult; }
}
复制代码


package test;
import java.util.ArrayList;import java.util.Collections;import java.util.List;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;import java.util.concurrent.FutureTask;import test.TestResult;
public class test1 { public static void main(String[] args) throws Exception, ExecutionException { System.out.println("输入参数URL:http://www.baidu.com,请求总次数:100,并发数10");
String url = "http://www.baidu.com"; ExecutorService executor = Executors.newFixedThreadPool(10); long sumTime = 0; List<TestResult> list = new ArrayList<>(); for (int i = 0; i < 100; i++) { LoadThread loadThread = new LoadThread("thread"+i,url); Future<TestResult> result = executor.submit(loadThread); long time = ((TestResult)result.get()).getTime(); sumTime+=time; list.add((TestResult)result.get());// System.out.println(((TestResult)result.get()).getTime());
} Collections.sort(list); System.out.println("响应参数:"); System.out.println("平局响应时间(毫秒):"+(sumTime/100)); System.out.println("95% 响应时间:"+list.get(94).getTime());
}
}
复制代码


输入参数 URL:http://www.baidu.com,请求总次数:100,并发数 10

响应参数:

平局响应时间(毫秒):30

95% 响应时间:32

用户头像

三板斧

关注

程咬金的三板斧 2018.10.08 加入

1、原理 2、实践 3、总结

评论

发布
暂无评论
架构师训练营 1 期 - 第七周 - 性能优化1