JAVA

简单多线程压测接口

2019-07-30  本文已影响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以下占了一半。
上一篇 下一篇

猜你喜欢

热点阅读