架构师训练营作业 -20200719
用你熟悉的编程语言写一个WEB性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95%响应时间。用这个工具以10并发、100次请求压测www.baidu.com
以下代码基于JAVA语言开发,压测“https://time.geekbang.org/”。
/**
* 处理HTTP请求的工具类
* @author xiaofy
*/
public class HttpUtil {
/**
* 向指定URL发送GET方法的请求
* @param url 发送请求的URL
* @return URL 所代表远程资源的响应结果
*/
public String sendGet(String url) {
String result = "";
BufferedReader in = null;
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "/");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
}
/**
* 进行性能测试的进程
* @author xiaofy
*/
public class PerformanceTestTask implements Callable<List<Long>> {
/**
* 待访问的URL
*/
private String url;
/**
* 重复次数
*/
private int repeat;
private HttpUtil httpUtil = new HttpUtil();
@Override
public List<Long> call() throws Exception {
List<Long> result = new ArrayList<Long>();
for(int i = 0; i < this.repeat; i++) {
long start = System.currentTimeMillis();
httpUtil.sendGet(this.url);
long end = System.currentTimeMillis();
long period = end - start;
result.add(period);
}
return result;
}
/**
* 构造函数
*/
public PerformanceTestTask(String url, int repeat) {
this.url = url;
this.repeat = repeat;
}
}
/**
* 主函数类
* @author xiaofy
*/
public class PerformanceTestMain {
/**
* 待测试的URL
*/
private static final String TEST_URL = "https://time.geekbang.org/";
/**
* 线程数量
*/
private static final int THREAD_COUNT = 10;
/**
* 重复访问次数
*/
private static final int REPEAT_TIME = 100;
/**
* 主函数
* @param args 入口参数
*/
public static void main(String[] args) {
//创建线程池
ExecutorService executor = Executors.newCachedThreadPool();
//初始化待执行的任务
List<FutureTask<List<Long>>> taskList = new ArrayList<FutureTask<List<Long>>>();
for(int i = 0; i < THREAD_COUNT; i++) {
PerformanceTestTask task = new PerformanceTestTask(TESTURL, REPEATTIME);
FutureTask<List<Long>> futureTask = new FutureTask<List<Long>>(task);
taskList.add(futureTask);
executor.submit(futureTask);
}
//保存所有的执行时间
List<Long> result = new ArrayList<Long>();
//汇总每个任务的执行结果
try {
for(int i = 0; i < taskList.size(); i++) {
FutureTask<List<Long>> futureTask = taskList.get(i);
if(futureTask.get() != null){
List<Long> list = futureTask.get();
if(list != null && list.size() > 0) {
for(int j = 0; j < list.size(); j++) {
result.add(list.get(j));
}
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
//关闭线程池
executor.shutdown();
//计算平均响应时间
double average = getAverage(result);
System.out.println("平均响应时间(毫秒):" + average);
//计算95%访问时间
Collections.sort(result);
long nintyFivePeriod = getNintyFivePeriod(result);
System.out.println("95%响应时间(毫秒):" + nintyFivePeriod);
}
/**
* 计算平均响应时间
* @param list 执行结果
* @return 平均响应时间
*/
private static double getAverage(List<Long> result) {
long sum = 0;
for(int i = 0; i < result.size(); i++) {
sum += result.get(i);
}
return ((double)sum / result.size());
}
/**
* 获取95%响应时间
* @param result 执行结果
* @return 95%响应时间
*/
private static long getNintyFivePeriod(List<Long> result) {
Collections.sort(result);
int pos = getNintyFivePosition(result);
if(result.size() >= pos) {
return result.get(pos - 1);
}
return 0;
}
/**
* 获取95%访问的下标
* @param result 执行结果
* @return 95%响应的下标
*/
private static int getNintyFivePosition(List<Long> result) {
int size = result.size();
int nintyFiveIndex = (int)(size * 0.95);
return nintyFiveIndex;
}
}
执行的响应结果如下:

评论