写点什么

架构师培训第七周练习

用户头像
小蚂蚁
关注
发布于: 2020 年 07 月 22 日

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

 

并发数、吞吐量、平均响应时间三者之间关系







性能测试阶段:系统并发访问数在系统的指定目标之内,系统硬件资源处于不饱合,此时系统的响应时间短,系统吞吐量未到达系统上线,所以吞吐量处于线性增长趋势,响应时间比较短,增长缓慢。

负载测试阶段:随着并发用户数的增加,系统硬件资源利用率上升,直到系统某些硬件资源达到饱和状态,此时由于需要等待硬件资源的使用,并发请求来不及及时处理,如果继续增加并发数,系统吞吐量增加缓慢,达到系统临界点后系统吞吐量开始降低,响应时间快速增长。

压力测试阶段:系统资源使用率到达饱和状态之后,继续增加并发量,此时系统吞吐量快速降低,直到系统压跨,响应时间无线长,系统不再处理任何请求。

  

2、用你熟悉的编程语言写一个 web 性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com

 

(1)压测类 WebLoadTester.java

package com.cfcc.demo;

 

import java.util.Collections;

import java.util.Comparator;

import java.util.Iterator;

import java.util.concurrent.CopyOnWriteArrayList;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

 

public class WebLoadTester {

    // 总共请求数

    private int totalNums = 100;

    // 并发数

    private int concurrentNums = 10;

    // 压测地址

    private String url;

 

    public WebLoadTester(int totalNums, int concurrentNums, String url) {

        this.totalNums = totalNums;

        this.concurrentNums = concurrentNums;

        this.url = url;

    }

 

    public LoadTestResult run() throws InterruptedException {

        // 用于协调线程执行,并发数10, 请求100次

        CountDownLatch countDownLatch = new CountDownLatch(totalNums * concurrentNums);

        CopyOnWriteArrayList timecollection = new CopyOnWriteArrayList<Object>();

        // 创建线程池用于执行线程

        ExecutorService threadPool = Executors.newFixedThreadPool(this.concurrentNums);

        // 请求100次

        for (int j = 0; j < totalNums; j++) {

            // 每次并发为10

            for (int i = 0; i < concurrentNums; i++) {

 

                RequestThread requestThread = new RequestThread(url, countDownLatch, timecollection);

                threadPool.execute(requestThread);

            }

            // 间隔一秒

            Thread.sleep(1000);

        }

        // 等待所有线程执行完毕

        countDownLatch.await();

 

        LoadTestResult result = new LoadTestResult();

 

        // 响应时间排序

        Collections.sort(timecollection, new Comparator<Object>() {

 

            public int compare(Object o1, Object o2) {

                Long l1 = (Long) o1;

                Long l2 = (Long) o2;

                return l1.compareTo(l2);

            }

        });

        if (timecollection.size() > 0) {

            // 计算95%的响应时间

            int index = timecollection.size() * 95 / 100;

            result.setPercent95Time((Long) timecollection.get(index));

            // 计算平均响应时间

            Long total = (long) 0;

            for (Iterator iterator = timecollection.iterator(); iterator.hasNext();) {

                Long object = (Long) iterator.next();

                total = total + object;

            }

            result.setAverageTime(total / timecollection.size());

        }

        return result;

    }

 

}

 

(2)压测线程类 RequestThread.java

package com.cfcc.demo;

 

import java.security.KeyManagementException;

import java.security.NoSuchAlgorithmException;

import java.security.cert.X509Certificate;

import java.util.concurrent.CopyOnWriteArrayList;

import java.util.concurrent.CountDownLatch;

import javax.net.ssl.SSLContext;

import javax.net.ssl.TrustManager;

import javax.net.ssl.X509TrustManager;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.apache.http.client.HttpClient;

import org.apache.http.client.methods.HttpGet;

import org.apache.http.conn.ClientConnectionManager;

import org.apache.http.conn.scheme.Scheme;

import org.apache.http.conn.scheme.SchemeRegistry;

import org.apache.http.conn.ssl.SSLSocketFactory;

import org.apache.http.impl.client.DefaultHttpClient;

 

public class RequestThread implements Runnable {

    private CountDownLatch countDownLatch;

    private String requestUrl;

    private CopyOnWriteArrayList timecollection;

    private Log log = LogFactory.getLog(RequestThread.class);

 

    public RequestThread(String requestUrl, CountDownLatch countDownLatch,CopyOnWriteArrayList timecollection) {

        this.requestUrl = requestUrl;

        this.countDownLatch = countDownLatch;

        this.timecollection = timecollection;

    }

   

    private static void sslClient(HttpClient httpClient) {

        try {

            SSLContext ctx = SSLContext.getInstance("TLS");

            X509TrustManager tm = new X509TrustManager() {

                public X509Certificate[] getAcceptedIssuers() {

                    return null;

                }

                public void checkClientTrusted(X509Certificate[] xcs, String str) {

                 

                }

                public void checkServerTrusted(X509Certificate[] xcs, String str) {

                 

                }

            };

            ctx.init(null, new TrustManager[] { tm }, null);

            SSLSocketFactory ssf = new SSLSocketFactory(ctx);

            ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

            ClientConnectionManager ccm = httpClient.getConnectionManager();

            SchemeRegistry registry = ccm.getSchemeRegistry();

            registry.register(new Scheme("https", 443, ssf));

        } catch (KeyManagementException ex) {

            throw new RuntimeException(ex);

        } catch (NoSuchAlgorithmException ex) {

        throw new RuntimeException(ex);

        }

    }

 

    public void run() {

        try {

            HttpClient httpClient = new DefaultHttpClient();

            if (requestUrl.startsWith("https://")) {

                sslClient(httpClient);

            }

            HttpGet request = new HttpGet(requestUrl);

            //调用起始时间

            long begin = System.currentTimeMillis();

            httpClient.execute(request);

            //调用结束时间

            long end = System.currentTimeMillis();

            //计算调用时间

            long time = (end-begin);

            //放入list用于统计

            timecollection.add(time);

            countDownLatch.countDown();

        } catch (Exception e) {

            countDownLatch.countDown();

            log.error("请求失败",e);

        }

 

    }

 

}

(3)压测结果类,用于存放压测结果 LoadTestResult.java

package com.cfcc.demo;

 

public class LoadTestResult {

 

    // 95%的响应时间

    private Long percent95Time;

    // 平均响应时间

    private Long averageTime;

 

    public Long getPercent95Time() {

        return percent95Time;

    }

 

    public void setPercent95Time(Long percent95Time) {

        this.percent95Time = percent95Time;

    }

 

    public Long getAverageTime() {

        return averageTime;

    }

 

    public void setAverageTime(Long averageTime) {

        this.averageTime = averageTime;

    }

 

}

 

(4)测试main函数

package com.cfcc.demo;

 

public class Test {

 

    public static void main(String[] args) throws InterruptedException {

        //初始化压测类,并发10,访问100次,访问地址 https://www.baidu.com/

        WebLoadTester loader = new WebLoadTester(100,10,"https://www.baidu.com/");

        try {

            LoadTestResult result = loader.run();

            System.out.println("平均响应时间: "+result.getAverageTime()+" 毫秒");

            System.out.println("95%响应时间: "+result.getPercent95Time()+" 毫秒");          

        } catch (InterruptedException e) {

            System.out.println("请求失败:"+e.getMessage());

        }

    }

 

}

 

测试执行结果:

平均响应时间: 305 毫秒

95%响应时间: 812 毫秒



用户头像

小蚂蚁

关注

还未添加个人签名 2018.08.10 加入

还未添加个人简介

评论 (1 条评论)

发布
用户头像
请加“极客大学架构师训练营”标签,便于分类
2020 年 07 月 22 日 18:06
回复
没有更多了
架构师培训第七周练习