Week 07 命题作业

用户头像
卧石漾溪
关注
发布于: 2020 年 07 月 21 日

1.性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?

解答:

响应时间:

指应用系统从发出请求开始到收到最后响应数据所需要的时间。响应时间是

系统最重要的性能指标,直观的反映了系统的“快慢”。



并发数:

系统能够同时处理请求的数目,这个数字也反映了系统的负载特性。对于网站而言,并发数即系统并发用户数,指同时提交请求的用户数目,与此相对应,还有在线用户数(当前登录系统的用户数)和系统用户数(可能访问系统的总用户数)。



吞吐量:

指单位时间内系统处理的请求的数量,体现件系统的处理能力。

对于网站,可以用“请求数/秒”或是“页面数/秒”来衡量,也可以用“访问人数/天”或是“处理的

业务数小时”等来衡量。

TPS (每秒事务数)也是吞吐量的一个指标,

此外还有HPS ( 每秒HTTP请求数),

QPS (每秒查询数)等。



下面是吞吐量的计算公式:

吞吐量=( 1000/响应时间ms ) x并发数



上面的公式看起来并发数越高,响应时间越短,系统吞吐量就越大;但实际上,并发数并不是无限增加吞吐量就越大了,因为系统处理能力是有极限的,到达极限后,响应时间就会不断的增加,这样吞吐量就会不断下降了。



资源消耗与TPS性能曲线图:



并发用户访问响应时间曲线图:



由此可见,随着并发数的不断增大,吞吐量有以下几种情况发生:

a.当系统处于B点之前时,系统的吞吐量增加显著;

b.当系统处于B点与C点之间时,由于响应时间开始明显增加,导致系统的吞吐量增长放缓;

c.当系统处于C点和D点之间时,由于系统已经过了最大负载点,导致响应时间急剧增加,这样就使得系统的吞吐量开始下降,直到D点系统崩溃为止。



2.用你熟悉的编程语言写一个web性能压测工具,输入参数: URL,请求总次数,并发数。

输出参数:平均响应时间,95%响应时间。用这个测试工具以10并发、100次请求压测www .baidu.com。



解答:

核心测试类:


import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

import org.apache.http.client.ClientProtocolException;

/**
* 模拟压力测试
*
* @author YX
*
*
*/

public class StressTest3 {
// 测试接口地址
public static final String testUrl = "https://www.baidu.com";

// 总请求个数
public static final int requestTotal = 100;
// 同一时刻最大的并发线程的个数
public static final int concurrentThreadNum = 10;
public static void main(String[] args) throws InterruptedException {
List<Long> responseTimeList = Collections.synchronizedList(new ArrayList<Long>());
ExecutorService executorService = Executors.newCachedThreadPool();
CountDownLatch countDownLatch = new CountDownLatch(requestTotal);
Semaphore semaphore = new Semaphore(concurrentThreadNum);
for (int i = 0; i< requestTotal; i++) {
executorService.execute(()->{
try {
semaphore.acquire();
long startTime = System.currentTimeMillis();
String result = testRequestUri();
long endTime = System.currentTimeMillis();
responseTimeList.add(endTime - startTime);
//System.out.println((endTime - startTime)+"返回接口调用结果:"+result);
semaphore.release();
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
// 显示测试报告
countAndShowReport(responseTimeList);
}
//请求测试接口
private static String testRequestUri() throws ClientProtocolException, IOException {
return HttpClientUtil.get(testUrl);
}
// 计算测试总耗时及平均耗时,并显示测试报告
private static void countAndShowReport(List<Long> list){
long allTime = 0;// 总响应时间
long avgTime = 0;// 平均响应时间
long resp95Time = 0;// 95%响应时间
// 求总时间
for(Long temp : list){
allTime += temp;
}
// 求平均响应时间
avgTime = Math.round(allTime / list.size());
// 求95%响应时间
double p = 0.95;
int n = list.size();
Collections.sort(list);
double px = p*(n-1);
int i = (int)Math.floor(px);
double g = px - i;
if(g==0){
resp95Time = list.get(0);
}else{
resp95Time = (long)((1 - g) * list.get(i) + g * list.get(i+1));
}
// 打印测试结果报告
System.out.println(testUrl+"========测试执行完毕,执行情况如下:");
System.out.println("总请求数:"+requestTotal);
System.out.println("并发数:"+concurrentThreadNum);
System.out.println("平均响应时间(毫秒):"+avgTime);
System.out.println("95%响应时间(毫秒):"+resp95Time);
}
}

/*
其中一次的打印报告:
https://www.baidu.com========测试执行完毕,执行情况如下:
总请求数:100
并发数:10
平均响应时间(毫秒):455
95%响应时间(毫秒):2935
*/






HTTP请求工具类:


import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.net.URI;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* Http请求封装工具类
*/
public class HttpClientUtil {


private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

/**
* 封装HTTP POST方法
*
* @param
* @param
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static String post(String url, Map<String, String> paramMap) throws ClientProtocolException, IOException {
HttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
//设置请求和传输超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).build();
httpPost.setConfig(requestConfig);
List<NameValuePair> formparams = setHttpParams(paramMap);
UrlEncodedFormEntity param = new UrlEncodedFormEntity(formparams, "UTF-8");
httpPost.setEntity(param);
HttpResponse response = httpClient.execute(httpPost);
logger.info("************{}", response);
String httpEntityContent = getHttpEntityContent(response);
logger.info("************{}", httpEntityContent);
httpPost.abort();
logger.info("************{}", httpEntityContent);
return httpEntityContent;

}

/**
* 封装HTTP POST方法
*
* @param
* @param (如JSON串)
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static String post(String url, String data) throws ClientProtocolException, IOException {
HttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
//设置请求和传输超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).build();
httpPost.setConfig(requestConfig);
httpPost.setHeader("Content-Type", "text/json; charset=utf-8");
httpPost.setEntity(new StringEntity(URLEncoder.encode(data, "UTF-8")));
HttpResponse response = httpClient.execute(httpPost);
String httpEntityContent = getHttpEntityContent(response);
httpPost.abort();
return httpEntityContent;
}

/**
* 封装HTTP GET方法
*
* @param
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static String get(String url) throws ClientProtocolException, IOException {
HttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet();
//设置请求和传输超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).build();
httpGet.setConfig(requestConfig);
httpGet.setURI(URI.create(url));
HttpResponse response = httpClient.execute(httpGet);
String httpEntityContent = getHttpEntityContent(response);
httpGet.abort();
return httpEntityContent;
}

/**
* 封装HTTP GET方法
*
* @param
* @param
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static String get(String url, Map<String, String> paramMap) throws ClientProtocolException, IOException {
HttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet();
//设置请求和传输超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).build();
httpGet.setConfig(requestConfig);
List<NameValuePair> formparams = setHttpParams(paramMap);
String param = URLEncodedUtils.format(formparams, "UTF-8");
httpGet.setURI(URI.create(url + "?" + param));
HttpResponse response = httpClient.execute(httpGet);
String httpEntityContent = getHttpEntityContent(response);
httpGet.abort();
return httpEntityContent;
}

/**
* 封装HTTP PUT方法
*
* @param
* @param
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static String put(String url, Map<String, String> paramMap) throws ClientProtocolException, IOException {
HttpClient httpClient = HttpClients.createDefault();
HttpPut httpPut = new HttpPut(url);
//设置请求和传输超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).build();
httpPut.setConfig(requestConfig);
List<NameValuePair> formparams = setHttpParams(paramMap);
UrlEncodedFormEntity param = new UrlEncodedFormEntity(formparams, "UTF-8");
httpPut.setEntity(param);
HttpResponse response = httpClient.execute(httpPut);
String httpEntityContent = getHttpEntityContent(response);
httpPut.abort();
return httpEntityContent;
}

/**
* 封装HTTP DELETE方法
*
* @param
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static String delete(String url) throws ClientProtocolException, IOException {
HttpClient httpClient = HttpClients.createDefault();
HttpDelete httpDelete = new HttpDelete();
//设置请求和传输超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).build();
httpDelete.setConfig(requestConfig);
httpDelete.setURI(URI.create(url));
HttpResponse response = httpClient.execute(httpDelete);
String httpEntityContent = getHttpEntityContent(response);
httpDelete.abort();
return httpEntityContent;
}

/**
* 封装HTTP DELETE方法
*
* @param
* @param
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static String delete(String url, Map<String, String> paramMap) throws ClientProtocolException, IOException {
HttpClient httpClient = HttpClients.createDefault();
HttpDelete httpDelete = new HttpDelete();
//设置请求和传输超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).build();
httpDelete.setConfig(requestConfig);
List<NameValuePair> formparams = setHttpParams(paramMap);
String param = URLEncodedUtils.format(formparams, "UTF-8");
httpDelete.setURI(URI.create(url + "?" + param));
HttpResponse response = httpClient.execute(httpDelete);
String httpEntityContent = getHttpEntityContent(response);
httpDelete.abort();
return httpEntityContent;
}


/**
* 设置请求参数
*
* @param
* @return
*/
private static List<NameValuePair> setHttpParams(Map<String, String> paramMap) {
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
Set<Map.Entry<String, String>> set = paramMap.entrySet();
for (Map.Entry<String, String> entry : set) {
formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
return formparams;
}

/**
* 获得响应HTTP实体内容
*
* @param response
* @return
* @throws IOException
* @throws UnsupportedEncodingException
*/
private static String getHttpEntityContent(HttpResponse response) throws IOException, UnsupportedEncodingException {
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream is = entity.getContent();
BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String line = br.readLine();
StringBuilder sb = new StringBuilder();
while (line != null) {
sb.append(line + "\n");
line = br.readLine();
}
return sb.toString();
}
return "";
}
}



用户头像

卧石漾溪

关注

还未添加个人签名 2020.05.04 加入

还未添加个人简介

评论

发布
暂无评论
Week 07 命题作业