• 性能测试中QPS取样器和RT取样器


    之前写过一个性能测试框架中QPS取样器实现,总体思路是通过一个异步工具类com.funtester.frame.execute.Progress来统计各个线程自己的统计数据(响应时间),然后再依据线程数计算实时的QPS。

    但是这个思路很容易受到数据(响应时间)取样的样本大小影响,因为对于混合接口压测场景中,不同接口的响应时间可能会差别很大。所有通过之前的思路就需要优化了,经过一些尝试终于确定了新的方案。

    思路

    这个功能仅针对于静态压测模型来讲,因为动态压测模型实现思路已经很不一样了,强制统一不太合适。所以针对动态模型,我单独写了一个动态模型的QPS取样器,对于之前的静态模型,我重新实现了RT取样器。由于动态模型中并不会记录响应时间,暂时也没有增加RT取样器的计划。

    1. 对于静态模型的RT取样器。我添加了com.funtester.base.constaint.ThreadBase#INTERCEPTcom.funtester.base.constaint.ThreadBase#COUNT,通过控制这两个开关来实现不同的功能。通过一个异步线程接口控制台输出内容,来控制RT取样器工作状态。
    2. 对于动态模型中的QPS模型,用到了性能测试中的LongAdder,经过测试性能足够好。依然通过异步线程获取这个计数器的值当做QPS,然后每次重置即可。
    3. 对于动态模型中的线程模型,由于com.funtester.base.constaint.ThreadBase已经提供了com.funtester.base.constaint.ThreadBase#executeNum当做每个线程的计数器,由于单线程的,所以并不用考虑线程安全的问题。直接将任务池中的com.funtester.base.constaint.ThreadBase存活对象遍历一遍求和即可。

    实现

    静态模型

    取样器方法实现:

        /**
         * 取样器
         *
         * @param time
         */
        public static void statistic(int time) {
            INTERCEPT = true;
            sleep(time);
            INTERCEPT = false;
            CountUtil.FunIndex index = CountUtil.index(interceptCosts);
            logger.info("当前QPS:{}", interceptCosts.size() / time);
            logger.info("当前RT:{}", index.toString());
            interceptCosts = new Vector<>();
        }
    
    

    这里用到了com.funtester.utils.CountUtil#index,代码后面会附上。

    动态QPS模型

    之前写过一个基于Disruptor的动态QPS模型框架:

    但是经过实际使用,并不适合,二次开发的复杂程度较高,目前已经放弃了。不过由于部分用例已经用上了,新的框架还没时间验证,所以还会保留一阵子。

    关于Disruptor获取实时QPS的可以翻一翻上面的文章,下面是新写的框架实现:

                if (index++ % LOOP_INTERVAL == 0) logger.info("当前设计QPS:{},实际QPS:{} 活跃线程数:{}", qps, total.sumThenReset() / LOOP_INTERVAL as int, executor.getActiveCount())
    
    

    其中com.funtester.frame.execute.FunEventConcurrent#total作为单个测试任务的统计对象,这也是为以后多任务做铺垫。

    动态线程模型

    这个相对简单,不用考虑线程安全的问题,只是在每次输出增减内容之后输出当前任务池的信息即可。

    首先是任务池信息获取方法:

        /**
         * 获取实时当然任务池信息
         */
        public static synchronized void printInfo() {
            long s = threads.stream().collect(Collectors.summarizingInt(f -> f.executeNum)).getSum();
            sleep(1);
            long e = threads.stream().collect(Collectors.summarizingInt(f -> f.executeNum)).getSum();
            logger.info("当前任务数:{} QPS:{}", aliveSize(), e - s);
        }
    
    

    其次是在处理控制台输出内容的内部类稍微改造一下:

        private static class FunTester implements IFunController {
    
            boolean key = true;
    
            @Override
            public void run() {
                while (key) {
                    String input = getInput();
                    switch (input) {
                        case "+":
                            add();
                            break;
                        case "-":
                            reduce();
                            break;
                        case "*":
                            over();
                            key = false;
                            break;
                        default:
                            if (Regex.isMatch(input, "(F|f)\\d+")) THREAD_STEP = changeStringToInt(input.substring(1));
                            break;
                    }
                    FunThread.printInfo();
                }
            }
    
            @Override
            public void add() {
                range(THREAD_STEP).forEach(f -> {
                    addTask();
                    sleep(0.5);
                });
            }
    
            @Override
            public void reduce() {
                range(THREAD_STEP).forEach(f -> {
                    removeTask();
                    sleep(0.5);
                });
            }
    
            @Override
            public void over() {
                FunThread.stop();
                logger.info("动态结束任务!");
            }
    
        }
    

    Have Fun ~ Tester !

  • 相关阅读:
    MySQL中的事务
    MySQL中的锁
    MySQL查询更新所有满足条件的数据
    MySQL存储引擎
    MySQL架构
    MySQL中存储json格式数据
    Java反射破坏单例模式
    合唱队(华为OJ)
    Java实现生产者消费者问题
    Spring IOC + AOP 的实现
  • 原文地址:https://www.cnblogs.com/FunTester/p/16191847.html
Copyright © 2020-2023  润新知