架构师训练营 -Week07
发布于: 2020 年 07 月 23 日
一、性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?
吞吐量开始时会增加,系统响应时间不怎么变化。 到达峰值后吞吐量开始下降,并且响应时间开始变长。因为并发量达到一定程度,网卡,CPU,内存,磁盘 都会遇到性能瓶颈,导致系统处理能力下降,请求积压吞吐量下降,响应时间变长。
二、用你熟悉的编程语言写一个 web 性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com。
//http 请求工具类package crawler;import java.io.IOException;import java.nio.charset.Charset;import java.security.KeyManagementException;import java.security.NoSuchAlgorithmException;import java.security.cert.CertificateException;import java.util.regex.Matcher;import java.util.regex.Pattern;import javax.net.ssl.SSLContext;import javax.net.ssl.TrustManager;import javax.net.ssl.X509TrustManager;import org.apache.http.HttpEntity;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.config.Registry;import org.apache.http.config.RegistryBuilder;import org.apache.http.conn.socket.ConnectionSocketFactory;import org.apache.http.conn.socket.PlainConnectionSocketFactory;import org.apache.http.conn.ssl.SSLConnectionSocketFactory;import org.apache.http.entity.ContentType;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;import org.apache.http.util.EntityUtils;public class HttpPoster { public static CloseableHttpClient getHttpClient() { // 创建cookie store的本地实例 // CookieStore cookieStore = new BasicCookieStore(); // // 创建HttpClient上下文 // HttpClientContext context = HttpClientContext.create(); // context.setCookieStore(cookieStore); // // BasicClientCookie cookie = new BasicClientCookie("4&_device", // "android&3c00676f-0e58-3aaa-aae8-4a8cc5eb95bf&6.5.63"); // cookie.setDomain(".ximalaya.com"); //设置范围 // cookie.setPath("/"); // cookieStore.addCookie(cookie); //采用绕过验证的方式处理https请求 SSLContext sslcontext = null; try { sslcontext = createIgnoreVerifySSL(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } //设置协议http和https对应的处理socket链接工厂的对象 Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create() .register("http", PlainConnectionSocketFactory.INSTANCE) .register("https", new SSLConnectionSocketFactory(sslcontext)).build(); PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager( socketFactoryRegistry); return HttpClients.custom().setConnectionManager(connManager).build(); } /** * 绕过验证 * * @return * @throws NoSuchAlgorithmException * @throws KeyManagementException */ public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException { SSLContext sc = SSLContext.getInstance("SSLv3"); // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法 X509TrustManager trustManager = new X509TrustManager() { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } }; sc.init(null, new TrustManager[] { trustManager }, null); return sc; } public static String parseResponse(CloseableHttpResponse response) throws IOException { HttpEntity entity = response.getEntity(); ContentType contentType = ContentType.getOrDefault(entity); Charset charset = contentType.getCharset(); String mimeType = contentType.getMimeType(); // 获取字节数组 byte[] content = EntityUtils.toByteArray(entity); if (charset == null) { // 默认编码转成字符串 String temp = new String(content); String regEx = "(?=<meta).*?(?<=charset=[\\'|\\\"]?)([[a-z]|[A-Z]|[0-9]|-]*)"; Pattern p = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE); Matcher m = p.matcher(temp); if (m.find() && m.groupCount() == 1) { charset = Charset.forName(m.group(1)); } else { charset = Charset.forName("ISO-8859-1"); } } return new String(content, charset); }}//压测工具类package performance;import crawler.HttpPoster;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.CloseableHttpClient;import java.io.IOException;import java.util.Arrays;import java.util.Queue;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.CountDownLatch;import java.util.concurrent.CyclicBarrier;public class WebPressureTestUtil { public static class Time { private long averageTime; private long time95; private Long[] times; public long getAverageTime() { return averageTime; } public long getTime95() { return time95; } public Time(Long[] times) { this.times = times; Arrays.sort(times); } public void calculateAverageTime() { // long total = 0L; // for (int i = 0; i < times.length; i++) { // total += times[i]; // } // this.averageTime = total / times.length; this.averageTime = times[times.length / 2 - 1]; } public void calculateTime95() { int index = times.length * 95 / 100; this.time95 = times[index]; } } private static class Task implements Runnable { private CountDownLatch signal; private CountDownLatch finish; private String url; private long runCount; private Queue<Long> timeCostArray; public Task(CountDownLatch signal, CountDownLatch finish, String url, long runCount, Queue<Long> timeCostArray) { this.signal = signal; this.finish = finish; this.url = url; this.runCount = runCount; this.timeCostArray = timeCostArray; } @Override public void run() { CloseableHttpClient httpClient = HttpPoster.getHttpClient(); HttpGet get = new HttpGet(url); try { signal.await(); } catch (InterruptedException e) { e.printStackTrace(); } for (int i = 0; i < runCount; i++) { long start = System.currentTimeMillis(); try (CloseableHttpResponse response = httpClient.execute(get)) { timeCostArray.offer(System.currentTimeMillis() - start);// System.err.println("response:"+HttpPoster.parseResponse(response)); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } finish.countDown(); } } public static Time perform(String url, int totalNum, int concurrentNum) throws Exception { //准备指定并发数量的线程,执行http请求, //使用countdownlatch 触发并发执行 int runCount = totalNum / concurrentNum; int remainCount = totalNum % concurrentNum; CountDownLatch signal = new CountDownLatch(1); CountDownLatch finish = new CountDownLatch(concurrentNum); Queue<Long> timeCostArray = new ArrayBlockingQueue<>(totalNum); for (int i = 0; i < concurrentNum; i++) { if (i == concurrentNum - 1) { new Thread(new Task(signal, finish, url, runCount + remainCount, timeCostArray)).start(); } else { new Thread(new Task(signal, finish, url, runCount, timeCostArray)).start(); } } signal.countDown(); finish.await(); Long[] times = new Long[totalNum]; timeCostArray.toArray(times); return new Time(times); } public static void main(String[] args) throws Exception { Time time = perform("https://www.baidu.com/", 100, 10); time.calculateAverageTime(); time.calculateTime95(); System.err.println("平均响应时间:" + time.getAverageTime() + "ms"); System.err.println("95%响应时间:" + time.getTime95() + "ms"); }}
划线
评论
复制
发布于: 2020 年 07 月 23 日阅读数: 54
Just顾
关注
还未添加个人签名 2018.05.06 加入
还未添加个人简介
评论 (1 条评论)