第 7 周作业
性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?
一开始系统响应时间和吞吐量随着并发数的增加近似线性的在增加,过了 b 点以后,随着并发数的增加,TPS 的增加开始变缓了,到了 c 点到了最大值。
进一步增加并发数,TPS 的值开始下降。
原因是资源的消耗
1.开始没有并发请求的时候,服务器资源是空闲的,TPS 为 0,当并发开始增加,系统创建相应的线程去处理这些并发请求,
每个线程都能够获得 CPU 的调度,都可以有足够的内存空间供它使用,访问磁盘,访问网络资源都是够用的。所有 TPS 很快就处理完了。
并发数在增加,资源足够的情况下,TPS 就快速增加。并发越多,TPS 处理的数据就越多。
过了 b 点以后,这些资源就不足了,有部分线性需求等待 CPU 调度,这些线程处于等待状态,响应时间就会变长,TPS 的值就变缓了,但它还是在增加。
3,当到达 C 点,某些资源已经到达极限了,并发再增加,系统无法处理那么多线程,它的处理能力会越来越低,所以 TPS 反而下降了。
用你熟悉的编程语言写一个 Web 性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com。
package com.web.testing;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.*;
public class WebSiteTest {
private static final String USER_AGENT = "HttpClient/3.1/PP";
private static final String CHARSET_UTF = "UTF-8";
private MultiThreadedHttpConnectionManager httpConnectionManager = new MultiThreadedHttpConnectionManager();
private HttpClient httpClient = new org.apache.commons.httpclient.HttpClient(httpConnectionManager);
private ExecutorService executor;
/**
* 测试 url
*/
private String testUrl;
/**
* 请求总次数
*/
private Integer testLength;
/**
* 并发数
*/
private Integer currentCount;
private SortedMap<Long, Integer> testResult = new TreeMap<>();
public WebSiteTest(String testUrl, Integer testLength, Integer currentCount) {
this.testUrl = testUrl;
this.currentCount = currentCount;
this.testLength = testLength;
this.executor = Executors.newFixedThreadPool(currentCount);
}
/**
* 发起测试
*/
public void testing(Integer percentTime) {
for (int i = 0; i < testLength; i++) {
executor.execute(() -> {
long startTime = System.currentTimeMillis();
Integer result = null;
try {
result = httpGetTest(testUrl);
} catch (Exception e) {
System.out.println(e.getMessage());
}
long endTime = System.currentTimeMillis();
long time = endTime - startTime;
synchronized (testResult.getClass()) {
Integer getVal = testResult.get(time);
if (getVal == null) {
getVal = 0;
}
testResult.put(time, ++getVal);
}
});
}
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
//计算响应时长
testingResultTime(percentTime);
}
/**
* 响应时常
*/
public void testingResultTime(Integer percentTime) {
//总时长
Long timeCount = 0L;
// 95 总时长
Long timeCount95 = 0L;
// 统计 95 的数量
Double count95 = 0.0;
//用百分比转化为需要查看的请求数的平均响应时常
Double countTime = testLength percentTime 0.01;
for (HashMap.Entry<Long, Integer> entry : testResult.entrySet()) {
timeCount += entry.getKey() * entry.getValue();
if(count95 < countTime){
if((count95 = count95 + entry.getValue() * 1.0) >= countTime){
timeCount95 = timeCount;
}
}
}
System.out.println("平均响应时间:" + (timeCount / testLength));
System.out.println("95 平均响应时间:" + (timeCount95/countTime));
}
public Integer httpGetTest(String fullUrl) {
GetMethod method = new GetMethod(fullUrl);
method.getParams().setParameter(HttpMethodParams.HTTPCONTENTCHARSET, "utf-8");
method.addRequestHeader("User-Agent", USER_AGENT);
try {
return httpClient.executeMethod(method);
} catch (IOException e) {
e.printStackTrace();
}finally {
method.releaseConnection();
}
return 0;
}
}
评论