美文网首页JAVA
简单多线程压测接口

简单多线程压测接口

作者: 秦时的明月夜 | 来源:发表于2019-07-30 11:06 被阅读0次

    测试接口的性能

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import java.io.IOException;
    import java.io.RandomAccessFile;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.util.*;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class Test {
    
        //统计总消耗时间
        private static AtomicInteger sum = new AtomicInteger(0);
        //统计执行了多少次
        private static AtomicInteger count = new AtomicInteger(0);
        private static String SysLine = System.getProperty("line.separator");
    
        private static Logger log = LoggerFactory.getLogger(Test.class);
    
        public static void main(String[] args) {
                //存放token提供请求凭证
                List<String> tokenlist = new ArrayList<String>();
                //存放每次执行的时间
                List<Integer> timeList = new ArrayList<Integer>();
                String fileName = "token.txt";
                //读取参数
                tokenlist = readTxtLine(fileName);
                //线程数
                int threadCount = 20;
                //循环次数
                int num = 1;
                //固定的线程池
                ExecutorService pool = Executors.newFixedThreadPool(threadCount);
                //倒计数器
                CountDownLatch countDownLatch = new CountDownLatch(tokenlist.size() * num);
                for (int i = 0; i < num; i++) {
                    tokenlist.forEach((token) -> {
                        System.out.println(token);
                        pool.submit(new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    long time1 = System.currentTimeMillis();
                                    //测试内容
                                    testFunc();
                                    long time2 = System.currentTimeMillis();
                                    int time = (int) (time2 - time1);
                                    sum.getAndAdd(time);
                                    count.incrementAndGet();
                                    timeList.add(time);
                                } catch (Exception e) {
                                    log.error("sso test  error");
                                } finally {
                                    countDownLatch.countDown();
                                }
    
                            }
                        });
                    });
                }
                try {
                    countDownLatch.await();
                    pool.shutdownNow();
                    writeTokenToTxt("", "time.txt", true);
                    timeList.stream().forEach((time) -> {
                        String content = String.valueOf(time) + SysLine;
                        TestEnv1.writeTokenToTxt(content, "time.txt", false);
                    });
                    int maxTime = Collections.max(timeList);
                    int minTime = Collections.min(timeList);
                    log.info(SysLine
                           +"-----------总时间:" + sum.get()+"ms"+SysLine
                           +"-----------请求次数:" + count.get()+"次"+SysLine
                           +"-----------最大耗时:" + maxTime+"ms"+SysLine
                           +"-----------最小耗时:" + minTime+"ms"+SysLine
                           +"-----------平均每次请求时间:" + sum.get() * 1.000 / count.get()+"ms"+SysLine
                           +"-----------平均每秒请求次数:" + 1 / (sum.get() / 1000.000 / count.get())+"次/秒"+SysLine
                           +"-----------TPS:" + threadCount / (sum.get() * 1.000 / count.get() / 1000)+SysLine);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
    
        /**
         * 读取文件中参数
         * @param fileName
         * @return
         */
        public static List<String>  readTxtLine(String fileName){
            Path file = Paths.get(fileName);
            List<String> tokenlist = new ArrayList<>();
            try {
                tokenlist = Files.readAllLines(file);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return tokenlist;
        }
    
        /**
         * 测试方法
         */
        public static void testFunc(){
            log.info("这是测试方法");
        }
    
    
        /**
         * 将参数写入文件
         * @param content
         * @param fileName
         * @param clear
         */
        public static void writeTokenToTxt(String content,String fileName,boolean clear){
            RandomAccessFile randomFile = null;
            try {
                Path fpath = Paths.get(fileName);
                if(!Files.exists(fpath)) {
                    try {
                        Files.createFile(fpath);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }else{
                    if(clear){
                        Files.write(fpath,"".getBytes());
                    }
                }
                randomFile = new RandomAccessFile(fileName, "rw");
                long fileLength = randomFile.length();
                randomFile.seek(fileLength);
                randomFile.writeBytes(content);
                randomFile.close();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if(randomFile!=null){
                    try {
                        randomFile.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
    
        }
    

    token.txt是一些测试数据记录到文本中,比如登录账号,或者请求的token,供测试方法 testFunc调用。(我测试的接口需要登录,所以我需要通过用户账号,获取用户的token,因为用户量比较大,需要保存到文件token.txt中,再读取文件 )

    testFunc就是测试的方法,里面是详细的测试内容。代码中可以直接算出消耗的最大时间、最小时间、平均时间、和TPS。如果还需要其他参数的结果,可以把时间记录到文本中,我把每次执行的时间保存到time.txt中,后期我们可以操作文本,进行统计。使用脚本统计简单方便,awk工具就很好用。

    对保存的时间可以坐统计分析

    分组统计每个时间段的时间情况

    cat  time.txt|awk '{   if($1>=0 && $1<10){m["01-10"]+=1}
                            else if($1>=10&&$1<30){m["10-30"]+=1}
                            else{m["30--"]+=1}
                       }
                      END{ for (k in m)  print k,"\t", m[k]}' |sort -nrk2 
    ###如果分组太多也可以使用head -n 20只显示前几行
    .....(省略)m[k]}' |sort -nrk2|head -n 20
    
    image.png

    获取中位数

    cat time.txt|sort -nk1|awk '{m[++n]=$1}END{  
          if(n%2==1) print m[int(n/2)];
          else print (m[n/2]+m[n/2+1])/2}' 
    
    image.png
    图中获取的中位数是8因此可以说明testFunc内容消耗时间8ms以下占了一半。

    相关文章

      网友评论

        本文标题:简单多线程压测接口

        本文链接:https://www.haomeiwen.com/subject/tykgrctx.html