Loadrunner11模拟多客户端并发对服务器并发处理socket请求的能力进行性能测试,C语言编写的winsocket Vuser脚本比较常见和简单,Java由于第三方库的庞大,能做的事情很多,这里介绍一下用Java写的脚本模拟socket客户端的压力测试情况。
主要环境:
1,JDK1.6
2,LoadRunner11
3,ApacheMINA2.09
基本流程是:
1,以MINA写成的java 同步客户端,打包为jar文件,需要参数,在LR11中为File形式提供参数;
2,在LR11的Vuser Generator中选择建立Java Vuser
3,在Vuser Generator的Run-time Setting > Java Enviroment settings > Classpath 中选择 Add Jar or zip file,把打包的java mina同步客户端jar文件和必要的库文件引入。
4,Vuser Generator的 Parameters List设定页,新建一个File类型的参数列表PARAMS,引入实现编辑好的参数列文件。
5,在Vuser Generator的View Script,在Actions中加入Java socket客户端调用。
6,建立测试场景。
7,在LR11的Controller中引入测试场景,设定并发测试参数。
8,在LR11的Controller中启动场景对服务器进行并发测试。
9,在LR11和服务端日志中分析测试结果 。
部分代码:
MINA同步客户端
package lr.test1;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.ReadFuture;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
public class CommandSender {
private static Logger logger = Logger.getLogger(CommandSender.class.getName());
private String port ;
private String ip ;
private String cmdtype;
private int poolSize = 1;
private LinkedBlockingQueue pool;
private IoConnector connector = null;
private static int CMDTIMEOUT_MILL = 2000;//等待回应的超时时间(毫秒)
public CommandSender(String ip,String port, String cmdtype) {
this.ip = ip;
this.port = port;
this.cmdtype = cmdtype;
}
public String sendpacket(String cmd){
if( !initclient() ){
logger.error("Connect failed!");
return null;
}
String res = sendmsg(cmd);
this.close();
return res;
}
public boolean initclient() {
boolean res = true;
try {
connector = new NioSocketConnector();
connector.getSessionConfig().setUseReadOperation(true);
DefaultIoFilterChainBuilder chain = connector.getFilterChain();
ProtocolCodecFilter cd = new ProtocolCodecFilter(new minaCodeFactory(Charset.forName("UTF-8")));
chain.addLast("chainin", cd);
connector.getSessionConfig().setReadBufferSize(1024);
connector.getSessionConfig().setMaxReadBufferSize(2048);
pool = new LinkedBlockingQueue(poolSize);
for (int i = 0; i < poolSize; i++) {
ConnectFuture connectF = connector.connect(new InetSocketAddress(ip, Integer.valueOf(port)));
connectF.awaitUninterruptibly();
IoSession session = connectF.getSession();
pool.put(session);
}
} catch (Exception e) {
logger.error("Connected to server failed, "+e.toString());
res = false;
}
return res;
}
private String sendmsg(String msg){
IoSession session = null;
String res = "";
try {
session = pool.take();
if (session == null) {
logger.error("CommandSender sendmsg session null. ["+msg+"]");
return res;
};
WriteFuture writeF = session.write(msg).awaitUninterruptibly();
if (writeF.getException() != null) {
logger.error("CommandSender sendmsg,"+writeF.getException().getMessage()+",["+msg +"]");
}else if (writeF.isWritten() ){
ReadFuture readF = session.read();
if(readF.awaitUninterruptibly(CMDTIMEOUT_MILL,TimeUnit.MILLISECONDS)){
res = readF.getMessage().toString().trim();
logger.info("CommandSender sendmsg complete, response: "+ res + ",[" + msg + "]");
}else{
logger.error("CommandSender sendmsg,response timeout! ["+ msg +"]");
}
}else{
logger.error("CommandSender sendmsg error, "+msg);
}
} catch (Exception e) {
logger.error("CommandSender sendmsg error, "+e.toString());
}finally {
try {
pool.put(session);
} catch (Exception e) {
logger.error("CommandSender sendmsg error, "+e.toString());
}
}
return res;
}
public void close() {
this.connector.dispose();
}
}
package lr.test1;
public class LRJava1 {
/**
* @param args
*/
public static void main(String[] args) {
String ip = args[0];
String port = args[1];
String param = args[2];
String cmdtype = args[3];
CommandSender c = new CommandSender(ip,port,cmdtype);
c.sendpacket("^HEADER^"+ param +"^^content");
}
}
Vuser Script Actions部分代码:
/*
* LoadRunner Java script. (Build: _build_number_)
*
* Script Description:
*
*/
import lrapi.*;
import lr.test1.LRJava1;
public class Actions
{
public int init() throws Throwable {
return 0;
}//end of init
public int action() throws Throwable {
//设置集合点
lr.rendezvous("集合点");
lr.start_transaction("j1");
LRJava1.main(new String[]{"192.168.1.2","9999", "", "REQUEST1"});
lr.end_transaction("j1", lr.AUTO);
return 0;
}
public int end() throws Throwable {
return 0;
}//end of end
}