手写java性能测试框架第二版
作者:FunTester 发布时间:2023-03-15 14:07:31
标签: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性能测试框架的资料请关注脚本之家其它相关文章!
来源:http://169p.cn/86tb
0
投稿
猜你喜欢
- 一、Mybatis1、mybatis-config.xml<?xml version="1.0" encoding
- 命令行编译java文件import java.util.*;public class shuchu{ public
- List list=new ArrayList()是怎么回事首先明确List是接口,ArrayList是它的实现类以下两种方法都可以,但是不
- 本文实例为大家分享了java实现简单年龄计算器的具体代码,供大家参考,具体内容如下制作一个如下图年龄计算器根据题目,我做了一个由Calend
- 本文实例讲述了Java面向对象程序设计:类的定义,静态变量,成员变量,构造函数,封装与私有,this概念与用法。分享给大家供大家参考,具体如
- 约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;
- 前言本文主要给大家分享了关于java文字转语音播报的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧方法如下一、po
- 背景:在Android中按照数据保存的方式,可以分为如下几种Content Provider (用的SQLite实现),SQLite,Sha
- 容器适配器我们可以看出,栈中没有空间配置器(内存池),而是适配器适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目
- 前言:什么是多数据源?最常见的单一应用中最多涉及到一个数据库,即是一个数据源(Datasource)。那么顾名思义,多数据源就是在一个单一应
- 一、HTTP http请求 一般一个http请求包括以下三个部分: 1 请求方法,如get,pos
- 问题今天在springboot中使用mybatis的时候不能字段不能够进行自动映射,mybatis的版本是3.5.11,数据库是按照下划线进
- 当遇到以下场景:其他人写的单元测试影响统计结果一些需要调用外部接口的测试暂不运行需要在非本机环境上运行一些不回滚的单元测试则有必要选择以下方
- 1、在ActionSupport中有一个validate()方法,这个方法是验证方法,它会在execute()方法执行之前执行,所以能够起到
- 基本流foreach 实现了外部迭代,它是建立于集合的基础上;stream 流实现的是内部迭代中间操作与终端操作对任意集合使用 stream
- Struts2Struts2是在WebWork2基础发展而来的。和struts1一样, Struts2也属于MVC框架。不过有一点
- 前言:线程安全是并发编程中的重要关注点,造成线程安全问题的主要原因有两点,一是存在共享数据(也称临界资源),二是存在多条线程共同操作共享数据
- mybatis in foreach 双层嵌套需求:根据角色id,返回角色名称,入参是List<List> 类型的二维数组,需要
- mybatis初始化SqlSessionFactory失败总结原因有几点1.resources中的xml配置文件放错位置或者是放的太深加载不
- 缓存淘汰算法在高并发、高性能的质量要求不断提高时,我们首先会想到的就是利用缓存予以应对。第一次请求时把计算好的结果存放在缓存中,下次遇到同样