相信一万行代码的理论!
上期将了多线程基类和执行类,本期分享一下两种压测模式。一种是定量,即单线程循环次数固定;另一种是定时,即单线程执行时间固定。两种方式各有优劣,实际工作中个人偏向定量,好处多多,比较好做任务管理,参数定制等等,缺点就是误差相比定时较大,这一点可以通过适当延长压测次数达到。
虽然两个都是虚拟类,但是基本功能已经全部完成,具备了进行压测的能力,下一期讲解两个基于HTTPrequestbase
对象的压测实现类以及连接资源回收多线程类的代码。
性能测试系列视频如下:
过程中还发现了小BUG
,已经修复,欢迎各位多提提意见,关注FunTester
交流测试相关。
gitee地址:https://gitee.com/fanapi/tester
定量模式虚拟类:
package com.fun.base.constaint;
import com.fun.base.interfaces.MarkThread;
import com.fun.config.HttpClientConstant;
import com.fun.frame.excute.Concurrent;
import com.fun.frame.httpclient.GCThread;
import com.fun.utils.Time;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
/**
* 请求时间限制的多线程类,限制每个线程执行的次数
*
* <p>
* 通常在测试某项用例固定时间的场景下使用,可以提前终止测试用例
* </p>
*
* @param <T> 闭包参数传递使用,Groovy脚本会有一些兼容问题,部分对象需要tostring获取参数值
*/
public abstract class ThreadLimitTimesCount<T> extends ThreadBase {
private static final Logger logger = LoggerFactory.getLogger(ThreadLimitTimesCount.class);
public List<String> marks = new ArrayList<>();
/**
* 全局的时间终止开关
*/
private static boolean key = false;
/**
* 任务请求执行次数
*/
public int times;
public ThreadLimitTimesCount(T t, int times, MarkThread markThread) {
this.times = times;
this.t = t;
this.mark = markThread;
}
protected ThreadLimitTimesCount() {
super();
}
@Override
public void run() {
try {
before();
List<Long> t = new ArrayList<>();
long ss = Time.getTimeStamp();
for (int i = 0; i < times; i++) {
try {
threadmark = mark == null ? EMPTY : this.mark.mark(this);
long s = Time.getTimeStamp();
doing();
long e = Time.getTimeStamp();
excuteNum++;
long diff = e - s;
t.add(diff);
if (diff > HttpClientConstant.MAX_ACCEPT_TIME) marks.add(diff + CONNECTOR + threadmark);
if (status() || key) break;
} catch (Exception e) {
logger.warn("执行任务失败!", e);
errorNum++;
}
}
long ee = Time.getTimeStamp();
logger.info("执行次数:{},错误次数: {},总耗时:{} s", times, errorNum, (ee - ss) / 1000 + 1);
Concurrent.allTimes.addAll(t);
Concurrent.requestMark.addAll(marks);
} catch (Exception e) {
logger.warn("执行任务失败!", e);
} finally {
after();
}
}
/**
* 运行待测方法的之前的准备
*/
@Override
public void before() {
key = false;
}
@Override
public boolean status() {
return errorNum > 10;
}
/**
* 用于在某些情况下提前终止测试
*/
public static void stopAllThread() {
key = true;
}
@Override
protected void after() {
super.after();
marks = new ArrayList<>();
GCThread.stop();
}
}
定时模式虚拟类:
package com.fun.base.constaint;
import com.fun.base.interfaces.MarkThread;
import com.fun.config.HttpClientConstant;
import com.fun.frame.excute.Concurrent;
import com.fun.frame.httpclient.GCThread;
import com.fun.utils.Time;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
/**
* 请求时间限制的多线程类,限制每个线程执行的时间
* <p>
* 通常在测试某项用例固定时间的场景下使用,可以提前终止测试用例
* </p>
*
* @param <T> 闭包参数传递使用,Groovy脚本会有一些兼容问题,部分对象需要tostring获取参数值
*/
public abstract class ThreadLimitTimeCount<T> extends ThreadBase {
private static final Logger logger = LoggerFactory.getLogger(ThreadLimitTimeCount.class);
public List<String> marks = new ArrayList<>();
/**
* 全局的时间终止开关
*/
private static boolean key = false;
/**
* 任务请求执行时间,单位是秒
*/
public int time;
public ThreadLimitTimeCount(T t, int time, MarkThread markThread) {
this.time = time * 1000;
this.t = t;
this.mark = markThread;
}
protected ThreadLimitTimeCount() {
super();
}
@Override
public void run() {
try {
before();
List<Long> t = new ArrayList<>();
long ss = Time.getTimeStamp();
long et = ss;
while (true) {
try {
threadmark = mark == null ? EMPTY : this.mark.mark(this);
long s = Time.getTimeStamp();
doing();
et = Time.getTimeStamp();
excuteNum++;
long diff = et - s;
t.add(diff);
if (diff > HttpClientConstant.MAX_ACCEPT_TIME) marks.add(diff + CONNECTOR + threadmark);
if ((et - ss) > time || status() || key) break;
} catch (Exception e) {
logger.warn("执行任务失败!", e);
errorNum++;
}
}
long ee = Time.getTimeStamp();
logger.info("执行次数:{}, 失败次数: {},总耗时: {} s", excuteNum, errorNum, (ee - ss) / 1000 + 1);
Concurrent.allTimes.addAll(t);
Concurrent.requestMark.addAll(marks);
} catch (Exception e) {
logger.warn("执行任务失败!", e);
} finally {
after();
}
}
/**
* 用于在某些情况下提前终止测试
*/
public static void stopAllThread() {
key = true;
}
public boolean status() {
return errorNum > 10;
}
/**
* 运行待测方法的之前的准备
*/
@Override
public void before() {
key = false;
}
@Override
protected void after() {
super.after();
marks = new ArrayList<>();
GCThread.stop();
}
}