在用Jmeter进行性能测试时也许有人遇到过这样的问题:
测试时TPS相当大,一台,二台负载机都找不到拐点,最后准备好多台负载机才解决问题,而且管理这些机器时比较麻烦。
我们能不能解决这些问题呢?当然可以,我们可以自动动手来实现一个迭代器。之所以能够高效,是因为我们去掉了测试工具的诸多辅助功能。
比如实时计算当前TPS、平均响应时间;记录日志等待工作,所以能够更快。
废话少说,下面实现一个简单的迭代器,以备不时之需。
1.定义一个接口,说明要做什么;参照Junit与LoadRunner Java Vuser来定义。
package com.seling.thread;
public interface BaseTask extends Runnable {
/**
* 初始化操作
*/
public void init();
/**
* 具体迭代的内容,要执行的测试程序放在此方法中,可以有入参
* @param i
*/
public String action(int i);
/**
* 收尾工作
*/
public void end();
}
2.实现接口程序,也就是具体任务内容。
</pre><pre name="code" class="java">package com.seling.thread;
import org.apache.log4j.Logger;
import com.seling.test.UserDaoI;
import com.seling.test.UserDaoImpl;
public abstract class Task implements BaseTask {
private static Logger log = Logger.getLogger(Task.class);
private String threadNo;//入参示例,这里传入线程号,实际可参与对象
private UserDaoI ud;//此测待测试的接口
/**
* 通过构造方法来初始化入参
* @param thread
*/
public Task(String thread){
this.threadNo = thread;
}
@Override
public abstract void run();
@Override
public void init() {
// TODO Auto-generated method stub
log.info("init "+this.threadNo);
ud = new UserDaoImpl();
}
@Override
public String action(int i) {
// TODO Auto-generated method stub
log.info("action "+this.threadNo+" iterator "+i);
//System.out.println("action "+this.threadNo+" iterator "+i);
//测试ud.getUserById()接口
return ud.getUserById(this.threadNo+"-"+i);//这个是我们要测试的接口主法
}
@Override
public void end() {
// TODO Auto-generated method stub
}
}
package com.seling.thread;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.log4j.Logger;
public class TestTask extends Task {
private static Logger log = Logger.getLogger(TestTask.class);
private static AtomicLong totalfailRecords = new AtomicLong(0);
private static AtomicLong totalPassRecords = new AtomicLong(0);
private static int runTime = 30000 ;//测试执行时长,单位毫秒
public TestTask(String thread) {
super(thread);
}
/**
* 开5个线程执行任务,平时测试中开启多少个线程自己决定
*
* @param args
*/
public static void main(String args[]) {
for (int i = 1; i <= 5; i++) {
new Thread(new TestTask("t" + i)).start();//开启线程执行任务
}
}
@Override
public void run() {
this.init();
int i = 0;
boolean ifRun = true;
long start = System.currentTimeMillis();
while (ifRun) {
String user = this.action(i++);
if (null != user)//验证事务是否成功
totalPassRecords.incrementAndGet();
else
totalfailRecords.incrementAndGet();
// 模拟ThinkTime,单位毫秒,对于TPS过万的接口建议不用模拟ThinkTime
try {
TimeUnit.MILLISECONDS.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
long runInstance = end - start;
if(runInstance >= runTime){
ifRun = false;
//执行完之后计算TPS
System.out.println("Duration(ms): " + (runInstance));
System.out.println("---------------------------------------------");
System.out.println("pass trasactions : " + totalPassRecords.get());
System.out.println("fail trasactions : " + totalfailRecords.get());
System.out.println("TPS: " + totalPassRecords.get() / (runInstance / 1000));
System.out.println("---------------------------------------------");
Thread.currentThread().stop();
}
//log.info("Fail trasactions : " + totalfailRecords.get());
//log.info("Pass trasactions : " + totalPassRecords.get());
//System.out.println("Iterator : " + totalPassRecords.get());
}
}
}
代码贴完,上面只是简单的实现了一个迭代功能。
如果对于入参有更多要求,下面几个思路可以作参考:
1.下面入参改为传对象
public TestTask(String thread) {
super(thread);
}
2.可以在init()方法中从文件中获取参数
3.在TestTask定义新的方法专门用来生成参数
最后附上UserDaoI接口及实现。
UserDaoI:不能再简单了,纯为了演示而用
package com.seling.test;
public interface UserDaoI {
public String getUserById(String id);
public void inOrModifyUser(UserInfo userInfo);
public void delUser(String id);
}
UserDaoImpl:
package com.seling.test;
public class UserDaoImpl implements UserDaoI {
@Override
public String getUserById(String id) {
// TODO Auto-generated method stub
return id;
}
@Override
public void inOrModifyUser(UserInfo userInfo) {
// TODO Auto-generated method stub
System.out.println(userInfo.getUserName());
}
@Override
public void delUser(String id) {
// TODO Auto-generated method stub
System.out.println("del "+id);
}
}
UserInfo:
package com.seling.test;
public class UserInfo {
private String userId;
private String userName;
private String address;
private String tele;
private boolean male;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getTele() {
return tele;
}
public void setTele(String tele) {
this.tele = tele;
}
public boolean isMale() {
return male;
}
public void setMale(boolean male) {
this.male = male;
}
}
见笑