写点什么

架构师训练营第七章作业

用户头像
叮叮董董
关注
发布于: 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=112416700ns
avg response time(ms): 109.5
95% response time(ms): 99
七月 21, 2020 7:32:54 上午 com.function.tools.TimingThreadPool terminated
信息: Terminated: avg time=109266200ns



用户头像

叮叮董董

关注

还未添加个人签名 2020.04.08 加入

还未添加个人简介

评论

发布
暂无评论
架构师训练营第七章作业