写点什么

Web 性能压测工具

用户头像
A p7+
关注
发布于: 2020 年 11 月 08 日

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

测试结果



代码

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author Yangzhen
* @Description 1.单元测试类继承此类;
* 2.重写concurrentCode方法,定义自己的并发代码;
* 3.重写encapsulatingData方法,并在concurrentCode方法中调用,定义数据的拼装;
* 4.重写blockingMainThread方法,定义主线程阻塞策略
* @date 2018-12-26 10:06
**/
public abstract class AbstractConcurrentControl {
public static final int DEFAULT_CONCURRENT_CONTROL = 200;
private int times;
private int perTimes;
private boolean perRandom;
private CountDownLatch latch;
private CountDownLatch stopLatch;
private ThreadPoolExecutor threadPool;
private BlockingQueue blockingQueue;
public Random random = new Random();
// 总计并发执行的执行次数
private int exeTotal;
/**
* 记录耗时
*/
private List<Long> respTimeList = Collections.synchronizedList(new ArrayList<>());
/**
* 单位:ms
*/
private int interval;
public AbstractConcurrentControl(int times, int perTimes, int interval, boolean perRandom) {
this.times = times;
this.interval = interval;
this.perTimes = perTimes;
this.perRandom = perRandom;
blockingQueue = new LinkedBlockingQueue<Runnable>();
threadPool = new ThreadPoolExecutor(DEFAULT_CONCURRENT_CONTROL, DEFAULT_CONCURRENT_CONTROL, 100000, TimeUnit.MILLISECONDS, blockingQueue);
}
public AbstractConcurrentControl(int times, int perTimes, int interval) {
this(times, perTimes, interval, false);
}
public AbstractConcurrentControl(int times, int interval) {
this(times, 0, interval, true);
}
/**
* 并发执行线程
*
* @Title: process
* @date 2018年12月26日 上午11:19:20
*/
public final void process() {
// 持续并发次数
int i = 0;
int[] perTimesArray = new int[times];
for (int j = 0; j < times; j++) {
if (perRandom) {
perTimesArray[j] = random.nextInt(DEFAULT_CONCURRENT_CONTROL);
} else {
perTimesArray[j] = perTimes;
}
exeTotal = exeTotal + perTimesArray[j];
}
stopLatch = new CountDownLatch(exeTotal);
while ((times--) > 0) {
int perTime = perTimesArray[i];
i++;
System.out.println("当前次数: " + (i) + " 剩余次数: " + (times) + " , 随机推送次数:" + perTime);
latch = new CountDownLatch(perTime);
for (int j = 0; j < perTime; j++) {
threadPool.submit(new Runnable() {
@Override
public void run() {
try {
latch.await();
long start = System.currentTimeMillis();
concurrentCode();
long end = System.currentTimeMillis();
long diff = end - start;
respTimeList.add(diff);
stopLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
latch.countDown();
}
try {
TimeUnit.MILLISECONDS.sleep(interval);
} catch (InterruptedException e) {
}
}
System.out.println("请求总次数: " + exeTotal);
blockingMainThread();
}
/**
* 并发代码
*
* @Title: concurrentCode
* @date 2018年12月26日 下午2:05:25
*/
protected abstract void concurrentCode();
/**
* 并发数据
*
* @return
* @Title: encapsulatingData
* @date 2018年12月26日 下午2:06:14
*/
protected abstract <T> T encapsulatingData();
/**
* 阻塞主线程,防止JVM关闭,不建议使用Xxx.class.wait,可以使用TimeUnit.Seconds.sleep(200);
* 如果使用TimeUnit.Seconds.sleep(200),可能会出现异常,因为JVM已经关闭,而测试的线程可能没有执行完成
*
* @Title: blockingMainThread
* @date 2018年12月26日 下午6:55:03
*/
protected void blockingMainThread() {
if (this.threadPool == null) {
return;
}
try {
stopLatch.await();
analysis();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
this.threadPool.shutdown();
}
}
private void analysis() {
respTimeList.sort(Long::compareTo);
System.out.println("总响应次数:" + respTimeList.size());
long sum = respTimeList.stream().mapToLong(Long::longValue).sum();
System.out.println("平均响应时间:" + sum * 1.0 / 100 + "ms");
System.out.println("95%响应时间:" + respTimeList.get((int) (0.95 * exeTotal)) + "ms");
}
}



import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
public class WebStressTesting extends AbstractConcurrentControl {
public static final String REMOTE_URL = "https://www.baidu.com";
public WebStressTesting() {
super(10, 10, 0);
}
@Override
protected void concurrentCode() {
try {
query();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected <T> T encapsulatingData() {
return null;
}
public static void main(String[] args) {
WebStressTesting webStressTesting = new WebStressTesting();
webStressTesting.process();
}
public void query() throws Exception {
java.net.URL connURL = new java.net.URL(REMOTE_URL);
HttpURLConnection httpURLConnection = (HttpURLConnection) connURL.openConnection();
httpURLConnection.setRequestProperty("Accept", "*/*");
httpURLConnection.setRequestProperty("Connection", "Keep-Alive");
httpURLConnection.setRequestProperty("User-Agent",
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)");
httpURLConnection.connect();
// 定义BufferedReader输入流来读取URL的响应,并设置编码方式
BufferedReader in = new BufferedReader(new InputStreamReader(httpURLConnection
.getInputStream(), "UTF-8"));
String line;
String result = "";
// 读取返回的内容
while ((line = in.readLine()) != null) {
result += line;
}
}
}



发布于: 2020 年 11 月 08 日阅读数: 37
用户头像

A p7+

关注

还未添加个人签名 2020.06.05 加入

还未添加个人简介

评论

发布
暂无评论
Web 性能压测工具