手写java性能测试框架第二版

 更新时间:2022年07月21日 15:25:55   作者:FunTester  
这篇文章主要为大家介绍了手写java性能测试框架第二版实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

依照领导要求区分了两种压测模式:固定次数压测和固定时间压测。此前一直沿用的都是固定次数,所以本次第二版剥离了固定次数的模式增加了固定时间的模式。

这是第一版:性能测试框架

第二版的threadbase代码如下

package com.fun.base.constaint;
import com.fun.frame.SourceCode;
import java.util.concurrent.CountDownLatch;
/**
 * 多线程任务基类,可单独使用
 */
public abstract class ThreadBase<T> extends SourceCode implements Runnable {
    /**
     * 计数锁
     * <p>
     * 会在concurrent类里面根据线程数自动设定
     * </p>
     */
    CountDownLatch countDownLatch;
    /**
     * 用于设置访问资源
     */
    public T t;
    protected ThreadBase() {
        super();
    }
    /**
     * groovy无法直接访问t,所以写了这个方法
     *
     * @return
     */
    public String getT() {
        return t.toString();
    }
    /**
     * 运行待测方法的之前的准备
     */
    protected abstract void before();
    /**
     * 待测方法
     *
     * @throws Exception
     */
    protected abstract void doing() throws Exception;
    /**
     * 运行待测方法后的处理
     */
    protected abstract void after();
    public void setCountDownLatch(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }
}

固定次数模式的压测虚拟类

package com.fun.base.constaint;
import com.fun.frame.excute.Concurrent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import static com.fun.utils.Time.getTimeStamp;
/**
 * 请求时间限制的多线程类,限制每个线程执行的次数
 *
 * <p>
 * 通常在测试某项用例固定时间的场景下使用,可以提前终止测试用例
 * </p>
 *
 * @param <T> 闭包参数传递使用,Groovy脚本会有一些兼容问题,部分对象需要tostring获取参数值
 */
public abstract class ThreadLimitTimes<T> extends ThreadBase {
    private static final Logger logger = LoggerFactory.getLogger(ThreadLimitTimes.class);
    /**
     * 任务请求执行次数
     */
    public int times;
    /**
     * 用于设置访问资源
     */
    public T t;
    public ThreadLimitTimes(T t, int times) {
        this(times);
        this.t = t;
    }
    public ThreadLimitTimes(int times) {
        this();
        this.times = times;
    }
    protected ThreadLimitTimes() {
        super();
    }
    /**
     * groovy无法直接访问t,所以写了这个方法
     *
     * @return
     */
    public String getT() {
        return t.toString();
    }
    @Override
    public void run() {
        try {
            before();
            List<Long> t = new ArrayList<>();
            long ss = getTimeStamp();
            for (int i = 0; i < times; i++) {
                long s = getTimeStamp();
                doing();
                long e = getTimeStamp();
                t.add(e - s);
            }
            long ee = getTimeStamp();
            logger.info("执行次数:{},总耗时:{}", times, ee - ss);
            Concurrent.allTimes.addAll(t);
        } catch (Exception e) {
            logger.warn("执行任务失败!", e);
        } finally {
            if (countDownLatch != null)
                countDownLatch.countDown();
            after();
        }
    }
    /**
     * 运行待测方法的之前的准备
     */
    protected abstract void before();
    /**
     * 待测方法
     *
     * @throws Exception
     */
    protected abstract void doing() throws Exception;
    /**
     * 运行待测方法后的处理
     */
    protected abstract void after();
}

固定时间模式虚拟类

package com.fun.base.constaint;
import com.fun.frame.excute.Concurrent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import static com.fun.utils.Time.getTimeStamp;
/**
 * 请求时间限制的多线程类,限制每个线程执行的时间
 * <p>
 * 通常在测试某项用例固定时间的场景下使用,可以提前终止测试用例
 * </p>
 *
 * @param <T> 闭包参数传递使用,Groovy脚本会有一些兼容问题,部分对象需要tostring获取参数值
 */
public abstract class ThreadLimitTime<T> extends ThreadBase {
    /**
     * 全局的时间终止开关
     */
    private static boolean key = false;
    private static final Logger logger = LoggerFactory.getLogger(ThreadLimitTime.class);
    /**
     * 任务请求执行时间,单位是秒
     */
    public int time;
    /**
     * 用于设置访问资源
     */
    public T t;
    public ThreadLimitTime(T t, int time) {
        this(time);
        this.t = t;
    }
    public ThreadLimitTime(int time) {
        this();
        this.time = time * 1000;
    }
    protected ThreadLimitTime() {
        super();
    }
    @Override
    public void run() {
        try {
            before();
            List<Long> t = new ArrayList<>();
            long ss = getTimeStamp();
            while (true) {
                long s = getTimeStamp();
                doing();
                long e = getTimeStamp();
                t.add(e - s);
                if ((e - ss) > time || key) break;
            }
            long ee = getTimeStamp();
            logger.info("执行时间:{} s,总耗时:{}", time / 1000, ee - ss);
            Concurrent.allTimes.addAll(t);
        } catch (Exception e) {
            logger.warn("执行任务失败!", e);
        } finally {
            if (countDownLatch != null)
                countDownLatch.countDown();
            after();
        }
    }
    /**
     * 用于在某些情况下提前终止测试
     */
    public static void stopAllThread() {
        key = true;
    }
}

这里我多加了一个终止测试的key,暂时没有用,以防万一。之所以没有采用另起线程去计时原因有二:进行测试过程中无论如何都会记录时间戳,多余的计算比较时间戳大小消耗性能很低,可以忽略;另起线程设计麻烦,在发生意外情况时缺少第二种保险措施。

HTTPrequestbase为基础的多线程类

下面是两种实现类的Demo,以HTTPrequestbase作为基础的多线程类。

固定次数模式的多线程类

/**
 * http请求多线程类
 */
public class RequestThreadTimes extends ThreadLimitTimes {
    static Logger logger = LoggerFactory.getLogger(RequestThreadTimes.class);
    /**
     * 请求
     */
    public HttpRequestBase request;
    /**
     * 单请求多线程多次任务构造方法
     *
     * @param request 被执行的请求
     * @param times   每个线程运行的次数
     */
    public RequestThreadTimes(HttpRequestBase request, int times) {
        this.request = request;
        this.times = times;
    }
    @Override
    public void before() {
        GCThread.starts();
    }
    @Override
    protected void doing() throws Exception {
        getResponse(request);
    }
    @Override
    protected void after() {
        GCThread.stop();
    }
    /**
     * 多次执行某个请求,但是不记录日志,记录方法用 loglong
     * <p>此方法只适应与单个请求的重复请求,对于有业务联系的请求暂时不能适配</p>
     *
     * @param request 请求
     * @throws IOException
     */
    void getResponse(HttpRequestBase request) throws IOException {
        CloseableHttpResponse response = ClientManage.httpsClient.execute(request);
        String content = FanLibrary.getContent(response);
        if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
            logger.warn("响应状态码:{},响应内容:{}", content, response.getStatusLine());
        response.close();
    }
}

固定时间模式的多线程类

package com.fun.frame.thead;
import com.fun.base.constaint.ThreadLimitTime;
import com.fun.frame.httpclient.ClientManage;
import com.fun.frame.httpclient.FanLibrary;
import com.fun.frame.httpclient.GCThread;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
/**
 * http请求多线程类
 */
public class RequestThreadTime extends ThreadLimitTime {
    static Logger logger = LoggerFactory.getLogger(RequestThreadTime.class);
    /**
     * 请求
     */
    public HttpRequestBase request;
    /**
     * 单请求多线程多次任务构造方法
     *
     * @param request 被执行的请求
     * @param times   每个线程运行的次数
     */
    public RequestThreadTime(HttpRequestBase request, int time) {
        this.request = request;
        this.time = time;
    }
    @Override
    public void before() {
        GCThread.starts();
    }
    @Override
    protected void doing() throws Exception {
        getResponse(request);
    }
    @Override
    protected void after() {
        GCThread.stop();
    }
    /**
     * 多次执行某个请求,但是不记录日志,记录方法用 loglong
     * <p>此方法只适应与单个请求的重复请求,对于有业务联系的请求暂时不能适配</p>
     *
     * @param request 请求
     * @throws IOException
     */
    void getResponse(HttpRequestBase request) throws IOException {
        CloseableHttpResponse response = ClientManage.httpsClient.execute(request);
        String content = FanLibrary.getContent(response);
        if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
            logger.warn("响应状态码:{},响应内容:{}", content, response.getStatusLine());
        response.close();
    }
}

其中可以发现,差别就在于属性time还是times的设定。

使用Demo:

package com.fun;
import com.fun.base.constaint.ThreadLimitTime;
import com.fun.frame.SourceCode;
import com.fun.frame.excute.Concurrent;
import java.util.ArrayList;
import java.util.List;
public class AR extends SourceCode {
    public static void main(String[] args) {
        ThreadLimitTime<Object> threadLimitTime = new ThreadLimitTime<Object>(10) {
            /**
             * 运行待测方法的之前的准备
             */
            @Override
            protected void before() {
            }
            /**
             * 待测方法
             *
             * @throws Exception
             */
            @Override
            protected void doing() throws Exception {
                AR.test();
            }
            /**
             * 运行待测方法后的处理
             */
            @Override
            protected void after() {
            }
        };
        new Concurrent(threadLimitTime,5).start();
        FanLibrary.testOver();
    }
    public static void test() {
        synchronized (AR.class) {
            sleep(100);
            output("fun");
        }
    }
}

剩下的mysql和redis以及dubbo的Demo就不写了,各位看官看着发挥即可,更多关于java性能测试框架的资料请关注脚本之家其它相关文章!

相关文章

  • Java使用entrySet方法获取Map集合中的元素

    Java使用entrySet方法获取Map集合中的元素

    这篇文章主要为大家详细介绍了Java使用entrySet方法获取Map集合中的元素,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • mybatis-plus3.4.0逻辑删除报错的解决

    mybatis-plus3.4.0逻辑删除报错的解决

    这篇文章主要介绍了mybatis-plus3.4.0逻辑删除报错的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • Java编程发展历史(动力节点Java学院整理)

    Java编程发展历史(动力节点Java学院整理)

    Java的历史可以追溯到1991年4月,Sun公司的James Gosling领导的绿色计划(Green Project)开始着力发展一种分布式系统结构,使其能够在各种消费性电子产品上运行,他们使用了C/C++/Oak语言。由于多种原因,绿色计划逐渐陷于停滞状态
    2017-03-03
  • java 序列化对象 serializable 读写数据的实例

    java 序列化对象 serializable 读写数据的实例

    java 序列化对象 serializable 读写数据的实例,需要的朋友可以参考一下
    2013-03-03
  • JAVA设计模式之访问者模式详解

    JAVA设计模式之访问者模式详解

    这篇文章主要介绍了JAVA设计模式之访问者模式详解,访问者模式是对象的行为模式,访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,需要的朋友可以参考下
    2015-04-04
  • Java常用类库Apache Commons工具类说明及使用实例详解

    Java常用类库Apache Commons工具类说明及使用实例详解

    这篇文章主要介绍了Java常用类库Apache Commons工具类说明及使用实例详解,需要的朋友可以参考下
    2020-02-02
  • Java如何实现通过证书访问Https请求

    Java如何实现通过证书访问Https请求

    这篇文章主要介绍了Java如何实现通过证书访问Https请求,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Java解释器的运行过程介绍

    Java解释器的运行过程介绍

    今天小编就为大家分享一篇关于Java解释器的运行过程介绍,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-04-04
  • Java异常处理与throws关键字用法分析

    Java异常处理与throws关键字用法分析

    这篇文章主要介绍了Java异常处理与throws关键字用法,结合实例形式分析了java常见的异常、错误处理及throws关键字相关使用技巧、注意事项,需要的朋友可以参考下
    2019-01-01
  • Java 阻塞队列BlockingQueue详解

    Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下
    2022-06-06

最新评论