架构师训练营第七章作业
发布于: 2020 年 07 月 21 日
作业:用你熟悉的编程语言写一个 web 性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com。
测试类,用于模拟测试
public class TestCaseWeb { public static void main(String[] args) throws ExecutionException, InterruptedException { String url = "http://www.baidu.com"; int requestCount = 100; int concurrentCount =10; FunctionUtils functionUtils = new FunctionUtils(url,requestCount,concurrentCount); functionUtils.execute(); }}
并发工具类
public class FunctionUtils { private String url; private int requestCount; private int concurrentCount; private List<Long> responseTimeList = new ArrayList<>(); public FunctionUtils(String url, int requestCount, int concurrentCount) { this.url = url; this.requestCount = requestCount; this.concurrentCount = concurrentCount; } public void execute() throws InterruptedException, ExecutionException { TimingThreadPool threadPool = new TimingThreadPool(concurrentCount,concurrentCount,0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); List<HttpInvoke> tasks = new ArrayList<>(); ExecutorService pool = Executors.newFixedThreadPool(concurrentCount); HttpInvoke functionUtils = new HttpInvoke(url); for (int i = 0 ; i < 100 ; i++) { tasks.add(functionUtils); } List<Future<Long>> futures = threadPool.invokeAll(tasks); for (Future<Long> future : futures) { responseTimeList.add(future.get()); } double avgTime = responseTimeList.stream() .mapToLong(i -> i.longValue()).average().getAsDouble(); System.out.println("avg response time(ms): " + avgTime); System.out.println("95% response time(ms): " + responseTimeList.get(responseTimeList.size() * 95 / 100 - 1)); threadPool.shutdown(); }}
异步调用
public class HttpInvoke implements Callable<Long> { private String url; public HttpInvoke(String url){ this.url = url; } @Override public Long call() throws Exception { long l = System.currentTimeMillis(); synchronized (this) { String s = HttpClient.doGet(url); } return System.currentTimeMillis() - l; }}
调用客户端
public class HttpClient { public static String doGet(String httpurl) { HttpURLConnection connection = null; InputStream is = null; BufferedReader br = null; String result = null;// 返回结果字符串 try { // 创建远程url连接对象 URL url = new URL(httpurl); // 通过远程url连接对象打开一个连接,强转成httpURLConnection类 connection = (HttpURLConnection) url.openConnection(); // 设置连接方式:get connection.setRequestMethod("GET"); // 设置连接主机服务器的超时时间:15000毫秒 connection.setConnectTimeout(15000); // 设置读取远程返回的数据时间:60000毫秒 connection.setReadTimeout(60000); // 发送请求 connection.connect(); // 通过connection连接,获取输入流 if (connection.getResponseCode() == 200) { is = connection.getInputStream(); // 封装输入流is,并指定字符集 br = new BufferedReader(new InputStreamReader(is, "UTF-8")); // 存放数据 StringBuffer sbf = new StringBuffer(); String temp = null; while ((temp = br.readLine()) != null) { sbf.append(temp); sbf.append("\r\n"); } result = sbf.toString(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭资源 if (null != br) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != is) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } connection.disconnect();// 关闭远程连接 } return result; }}
自定义线程池
public class TimingThreadPool extends ThreadPoolExecutor { private final ThreadLocal<Long> startTime = new ThreadLocal<>(); private final Logger log = Logger.getLogger("TimingThreadPool"); private final AtomicLong numTasks = new AtomicLong(); private final AtomicLong totalTime = new AtomicLong(); public TimingThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); } @Override protected void beforeExecute(Thread t, Runnable r) { super.beforeExecute(t, r); log.info(String.format("Thread %s: start %s",t,r)); startTime.set(System.nanoTime()); } @Override protected void afterExecute(Runnable r, Throwable t) { try { long endTime = System.nanoTime(); long taskTime = endTime - startTime.get(); numTasks.incrementAndGet(); totalTime.addAndGet(taskTime); log.info(String.format("Thread %s: end %s, time=%dns",t,r,taskTime)); } finally { super.afterExecute(r,t); } } @Override protected void terminated() { try { log.info(String.format("Terminated: avg time=%dns",totalTime.get() / numTasks.get())); } finally { super.terminated(); } }}
结果
七月 21, 2020 7:32:54 上午 com.function.tools.TimingThreadPool afterExecute信息: Thread null: end java.util.concurrent.FutureTask@758d5147, time=99857200ns七月 21, 2020 7:32:54 上午 com.function.tools.TimingThreadPool afterExecute信息: Thread null: end java.util.concurrent.FutureTask@26eea04, time=112416700nsavg response time(ms): 109.595% response time(ms): 99七月 21, 2020 7:32:54 上午 com.function.tools.TimingThreadPool terminated信息: Terminated: avg time=109266200ns
划线
评论
复制
发布于: 2020 年 07 月 21 日阅读数: 50
叮叮董董
关注
还未添加个人签名 2020.04.08 加入
还未添加个人简介
评论