Web 性能压测工具
发布于: 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
版权声明: 本文为 InfoQ 作者【A p7+】的原创文章。
原文链接:【http://xie.infoq.cn/article/26e2547189cf4e787ce5ac5d4】。文章转载请联系作者。
A p7+
关注
还未添加个人签名 2020.06.05 加入
还未添加个人简介
评论