java测试代码
来源:互联网 发布:德国 知乎 编辑:程序博客网 时间:2024/06/05 11:19
最近在做一个项目时要测试TOMCAT和NIO的吞吐量,其实在网上有很大一批用来做测试的工具,也非常不错,但是我还是盟生了自已写一个测试用例,起初自是想针对本次项目的服务器进行测试,不过后再做的时候发现很多问题,比方说怎么样控制读包错误后再访问和写包错误后的再访还有就是服务器本身Socket的连接数是有限的,怎么样再服务器拒绝连接后的操作,拒绝后是否算一次请求等等.下面我把具体的思路讲一下吧~!(其实说到实现,我是写得非常烂的,贴出来只是为了交流一下,希望有大侠们能多指都一下).
对于我们来说一台机器只能用线程来模拟用户数,也就是一个用户就是一个线程.但是在我在做完后,发现在大批量用户处理请求时有时由于服务器的处理速度非常快时,可能线程启动的时间,比服务器把全部请求处理完的速度还要快,这样测出来的数据就很不准确了,比如说我们模拟1000个用户发送20000次请求数据.因为我们的线程是在一起动就进行数据的请求,当我们起动到第300个时就已经把这20000个数据都请求完毕了,这样其实,我们就只测到了并发300个用户的吞吐量,所以我们必须保证每一个线程都至少发送了一次以上的请求.于是我最后得到了二种方案,第一种就是起用平均制,也就是说归定每个用户发送多少请求.第二种就是猜用集体等待通知制.第一种我想大家都明白是怎么回事,我这里解释一下第二种吧,第二种是首先把线程全部起动,但不执行请求,而是全部挂起.等待主线程全部通知执行.(呵呵`!可能是比较笨的方法)最后我先择了第二种,因为我想要真实的模拟用户发送是不可能平均的....
接下来说一下,就是在整个测试程序中,我们可以用一种Keep-Alive方式和非Keep-Alive方式发送请求,这二种方式的性能差是非常大的,(Keep-Alive是说当开起一个Socket连接后,一个用户针对这个Socket是不关闭的,基一个Socket上不断连续的发送请求,而非Keep-Alive的方式就是每次请求都会有一个独立的Socket开启,其实大家都知道,请求响应的时间其本上是很小的,我们所花的时间都在Socket的连接上,所以Keep-Alive和非Keep-Alive的方式性能相差非常大)当我用Keep-Alive的方式做一个任务时又发现,当连接不间断的提出请求时,有由于请求过快,可能导致服务器数据响应错误.所以后来又修改了程序.好了废话也写了一堆了,呵呵,文笔不好,多见谅.~!下面把代码贴出来吧~!
LockObject.java
* @author Administrator
*
* 锁对像,存放着所有需要数据同步的锁对像
*/
public class LockObject ...{
public static byte[] taskNum = new byte[0]; //任务数量锁对像
public static byte[] responseError = new byte[0]; //响应错误
public static byte[] readError = new byte[0]; //读错误
public static byte[] writeError = new byte[0]; //写错误
public static byte[] succ = new byte[0]; //成功数
public static byte[] refuseError = new byte[0]; //拒绝数
}
GlobalObject.java
* @author Administrator
*
* 存放全局对像的.
*/
public class GlobalObject ...{
public static String Ipaddress = null; //测试服务器IP地址
public static int prot = 0; //测试服务器端口
public static int userNums = 0; //客户端模拟用户数
public static int alltaskNums = 0; //待测试的任务数
public static int responseError = 0; //响应错误数
public static int readError = 0; //读错误数
public static int writeError = 0; //写错误数
public static int succ = 0; //响应成功数
public static int refuseError = 0; //服务器拒绝错误
public static int taskNums = 0; //已完成的任务数
public static int responseByteNums =0; //测试服务器响应字节数
public static int KeepAliv = 1; //是否KeepAliv 默认是
public static String method = "POST"; //数据发送方式
}
GlobalMethod.java
* @author Administrator
*
* 存放全局方法,主要是做命令检查与解析.还有字符串分隔的,呵呵~!
* 由于JDK1.4提供的字符串分隔性能较低,所以自已实现了一个
*/
public class GlobalMethod ...{
/** *//**
* 解析命令
* @param cmd 命令字符串
* @return 返回boolean当解析成功时返回true否则返回flase
*/
public static boolean parseCmd(String cmd)
...{
boolean result = true;
if( cmd.indexOf("=")>0 )
...{
String[] cmdArray = GlobalMethod.split(cmd,'=');
if( cmdArray.length==2 )
...{
result = true;
String tempCmd = cmdArray[0].toLowerCase();
if( tempCmd.equals("server")) //测试服务器IP地址
...{
GlobalObject.Ipaddress = cmdArray[1];
}
else if( tempCmd.equals("prot") ) //测试服务器端口
...{
try
...{
GlobalObject.prot = Integer.parseInt(cmdArray[1]);
if( GlobalObject.prot<=0 || GlobalObject.prot>=65535 )
...{
System.out.println("protError");
result = false;
}
}
catch(NumberFormatException e)
...{
System.out.println("protError");
result = false;
}
}
else if( tempCmd.equals("users") ) //并发用户数
...{
try
...{
GlobalObject.userNums = Integer.parseInt(cmdArray[1]);
if( GlobalObject.userNums<=0 )
...{
System.out.println("usersError");
result = false;
}
}
catch(NumberFormatException e)
...{
System.out.println("usersError");
result = false;
}
}
else if( tempCmd.equals("task") )
...{
try
...{
GlobalObject.alltaskNums = Integer.parseInt(cmdArray[1]);
if( GlobalObject.alltaskNums<=0 )
...{
System.out.println("taskError");
result = false;
}
}
catch(NumberFormatException e)
...{
System.out.println("taskError");
result = false;
}
}
else if( tempCmd.equals("responsebyte") )
...{
try
...{
GlobalObject.responseByteNums = Integer.parseInt(cmdArray[1]);
if( GlobalObject.responseByteNums<=0 )
...{
result = false;
System.out.println("responseByteError");
}
}
catch(NumberFormatException e)
...{
System.out.println("responseByteError");
result = false;
}
}
/**//*else if( tempCmd.equals("KeepAliv") )
{
try
{
GlobalObject.KeepAliv = Integer.parseInt(cmdArray[1]);
if( GlobalObject.KeepAliv<0 )
{
result = false;
System.out.println("KeepAlivError");
}
}
catch(NumberFormatException e)
{
System.out.println("KeepAlivError");
result = false;
}
}
else if( tempCmd.equals("method") )
{
GlobalObject.method = cmdArray[1];
}*/
}
else
...{
result = false;
}
}
else
...{
result = false;
}
return result;
}
public static boolean CheckParam()
...{
// 检查参数是否全部到位
boolean result = true;
if( GlobalObject.alltaskNums==0 ) //查任务数
...{
result = false;
System.out.println("you must add task parameter");
}
if( GlobalObject.Ipaddress==null ) //检查服务器地址
...{
result = false;
System.out.println("you must add server parameter");
}
if( GlobalObject.prot==0 ) //检查服务器端口
...{
result = false;
System.out.println("you must add prot parameter");
}
if( GlobalObject.userNums==0 )
...{
result = false;
System.out.println("you must add users parameter");
}
if( GlobalObject.responseByteNums==0 )
...{
result = false;
System.out.println("you must add responseByte parameter");
}
return result;
}
/** *//**
* 按给定字符串,分解字符串
* @param st 待分解的字符串
* @param sep 分隔符
* @return String[]
*/
public static String[] split (String st, char sep) ...{
ArrayList alist = new ArrayList();
int len = st.length();
int pos = 0;
int fin = 0;
while (pos < len && (fin = st.indexOf(sep, pos)) != -1)...{
alist.add(st.substring(pos, fin ));
pos = fin + 1;
}
String remainder = st.substring(pos);
if (remainder.length() != 0)
...{
alist.add(remainder);
}
String[] ret = new String[alist.size()];
alist.toArray(ret);
return ret;
}
}
Task.java (Keep-Alive)
* @author Administrator
*
* 线程类
*/
public class Task extends Thread ...{
/**//*public static AtomicInteger responseError = new AtomicInteger(0); //响应错误发生次数
public static AtomicInteger readError = new AtomicInteger(0); //读错误发生次数
public static AtomicInteger writeError = new AtomicInteger(0); //写错误发生次数
public static AtomicInteger succ = new AtomicInteger(0); //成功次数
public static AtomicInteger taskNums = new AtomicInteger(0); //任务次数
public static AtomicInteger refuseError = new AtomicInteger(0); //服务器拒绝错误
*/
public static String CRLF = " ";
private Socket socket;
private OutputStream output;
private InputStream input;
private boolean isdo;
byte[] b = new byte[GlobalObject.responseByteNums]; //114 响应数据
public Task()
...{
socket = new Socket();
isdo = true;
}
/** *//**
* 发出结束线程
*
*/
public void endTask()
...{
isdo = false;
this.interrupt();
}
public void run() ...{
//向服务器发送的请求头数据
String headData = "POST /tSixServer/test HTTP/1.1" + Task.CRLF;
headData += "Connection: Keep-Alive" + Task.CRLF;
headData += "Host: "+ GlobalObject.Ipaddress + Task.CRLF + CRLF;
SocketAddress address = new InetSocketAddress(GlobalObject.Ipaddress,GlobalObject.prot);
//连接服务器
short isRefuse = 0;
try ...{
socket.connect(address);
socket.setKeepAlive(true);
input = socket.getInputStream();
}
catch (IOException e)
...{
synchronized(LockObject.refuseError)
...{
GlobalObject.refuseError++;
}
isRefuse++;
}
try ...{
sleep(300);
} catch (InterruptedException e5) ...{
// TODO 自动生成 catch 块
e5.printStackTrace();
}
short isPrint = 0;
while( isdo )
...{
if( GlobalObject.taskNums<GlobalObject.alltaskNums )
...{
//标识是否进行读操作,由于http协议是请求响应操作,当写操作出错,而无法恢复时候,
//就不可能有响应数据,这时应该放弃读操作.此标识就是标识当写操作出错时,不再进行读操作
//当为true时,说明写操作无误,可以进行读操作.
boolean isRead = true;
...{
short we = 0; //标识写错误是否已加
try
...{
//写数据
output = socket.getOutputStream();
output.write(headData.getBytes());
output.flush();
isRead = true;
}
catch(IOException e)
...{
if( isRefuse!=1 )
...{
synchronized(LockObject.writeError)
...{
GlobalObject.writeError++;
}
}
isRefuse = 2;
isRead = false;
try ...{
socket.close();
socket = null;
sleep(100);
socket = new Socket();
socket.connect(address);
socket.setKeepAlive(true);
input = socket.getInputStream();
}
catch (IOException e3)
...{
isRead = false;
synchronized(LockObject.refuseError)
...{
GlobalObject.refuseError++; //服务器拒绝
}
} catch (InterruptedException e4) ...{
e4.printStackTrace();
}
}
}
String responseHead = "";
if( isRead )
...{
try ...{
int nums = input.read(b);
if( nums!=GlobalObject.responseByteNums )
...{
synchronized(LockObject.readError)
...{
GlobalObject.readError++;
}
...{
try ...{
socket.close();
socket = null;
sleep(100);
socket = new Socket();
socket.connect(address);
socket.setKeepAlive(true);
input = socket.getInputStream();
}
catch (IOException e3)
...{
synchronized(LockObject.refuseError)
...{
GlobalObject.refuseError++;
}
}
catch (InterruptedException e)
...{
e.printStackTrace();
}
}
}
else
...{
responseHead = new String(b);
String[] responseArray = responseHead.split(Task.CRLF);
String[] tmp = responseArray[0].split(" ");
if( Integer.parseInt(tmp[1])==200 )
...{
synchronized(LockObject.succ)
...{
GlobalObject.succ++;
}
}
else
...{
synchronized(LockObject.responseError)
...{
GlobalObject.responseError++;
}
}
}
}
catch (IOException e)
...{
synchronized(LockObject.readError)
...{
GlobalObject.readError++;
}
...{
try
...{
socket.close();
socket = null;
sleep(100);
socket = new Socket();
socket.connect(address);
socket.setKeepAlive(true);
input = socket.getInputStream();
}
catch(IOException e1)
...{
synchronized(LockObject.refuseError)
...{
GlobalObject.refuseError++;
}
}
catch (InterruptedException e2)
...{
e2.printStackTrace();
}
}
}
catch(ArrayIndexOutOfBoundsException e)
...{
System.out.println(responseHead);
}
}
synchronized(LockObject.taskNum)
...{
GlobalObject.taskNums++;
}
}
else
...{
isdo = false;
}
}
}
}
Task_2.java (非Keep-Alive)
* @author Administrator
*
* 线程控制类
*/
public class ThreadPool ...{
private Task_2[] taskArray;
public ThreadPool(int size)
...{
taskArray = new Task_2[size];
for( int i=0;i<taskArray.length;i++ )
...{
taskArray[i] = new Task_2();
taskArray[i].start();
}
}
public void Start()
...{
for( int i=0;i<taskArray.length;i++ )
...{
synchronized(taskArray[i])
...{
taskArray[i].notifyAll();
}
}
}
}
MainTest.java
* @author Administrator
*
* 主线程类
*/
public class MainTest ...{
public static int taskNums = 0;
public static void main(String[] args) ...{
/**//*GlobalObject.Ipaddress = args[0]; //获得测试服务器IP地址
GlobalObject.prot = Integer.parseInt(args[1]); //获得测试服务器端口
GlobalObject.userNums = Integer.parseInt(args[2]); //获得模拟的用户数
GlobalObject.alltaskNums = Integer.parseInt(args[3]); //获得任务总数
GlobalObject.responseByteNums = Integer.parseInt(args[4]); //获得响应字节数
*/
/**//*GlobalObject.Ipaddress = args[0]; //获得测试服务器IP地址
GlobalObject.prot = Integer.parseInt(args[1]); //获得测试服务器端口
GlobalObject.userNums = Integer.parseInt(args[2]); //获得模拟的用户数
GlobalObject.alltaskNums = Integer.parseInt(args[3]); //获得任务总数
GlobalObject.responseByteNums = Integer.parseInt(args[4]); //获得响应字节数
*/
//把命令行传入的参数全部赋给程序
/**//* args = new String[5];
args[0] = "server=192.168.1.127";
args[1] = "prot=1650";
args[2] = "users=1";
args[3] = "task=10";
args[4] = "responseByte=31";*/
if( args.length==0 )
...{
System.out.println("缺少全部参数");
return;
}
for( int i=0;i<args.length;i++ )
...{
if( !GlobalMethod.parseCmd(args[i]) )
return;
}
//检查参数是否到位]
boolean isstest = true;
if( !GlobalMethod.CheckParam() )
return;
/**//*if( isstest )
return;*/
ThreadPool pool = new ThreadPool(GlobalObject.userNums);
while( GlobalObject.userNums>0 )
...{
try ...{
Thread.sleep(500);
} catch (InterruptedException e1) ...{
// TODO 自动生成 catch 块
e1.printStackTrace();
}
}
long time = System.currentTimeMillis();
pool.Start();
while( GlobalObject.taskNums<GlobalObject.alltaskNums )
...{
try ...{
Thread.sleep(100);
} catch (InterruptedException e) ...{
// TODO 自动生成 catch 块
e.printStackTrace();
}
}
time = System.currentTimeMillis() - time;
System.out.println("U:"+GlobalObject.userNums);
System.out.println("RE:"+GlobalObject.readError);
System.out.println("WE:"+GlobalObject.writeError);
System.out.println("E:"+GlobalObject.responseError);
System.out.println("refuse:"+GlobalObject.refuseError);
System.out.println("S:"+GlobalObject.succ );
System.out.println("T:"+time );
/**//*ThreadPoolExecutor producerPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(userNums);
int requestCount = 0;
Socket socket = new Socket();
SocketAddress address = new InetSocketAddress("59.42.253.239",8080);
try {
socket.connect(address);
} catch (IOException e1) {
// TODO 自动生成 catch 块
e1.printStackTrace();
}
System.out.println("start...");
long time = System.currentTimeMillis();
while( true )
{
TaskR task = new TaskR(socket);
producerPool.execute(task);
requestCount++;
if( requestCount>=taskNums )
break;
}
BlockingQueue queue = producerPool.getQueue();
while( queue.size()>0 )
{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
}
}
producerPool.shutdown();
time = System.currentTimeMillis() - time;
System.out.println("Error:"+Task.error.get() );
System.out.println("Succ:"+Task.succ.get());
System.out.println("Time:"+time);*/
}
}
其实,在实现上,我想最好是把Keep-Alive的测试也用NIO的方式去做,当有100个用户时实际上我们就挂起100个Socket,这样做的好处是客户机不用用开很多线程,这样就减少了线程的开销与线程间上下文切换的时间,用一个单线来处理.
- java测试代码
- Java游戏测试代码
- Java 测试代码
- hbase测试 java代码
- emqttd java代码测试
- Java 测试代码模板
- java并发测试代码
- Java测试代码段
- Java 测试代码段
- Java HelloWorld代码测试
- Java接口测试java代码
- 之前的java测试代码 性能测试
- 测试Java代码的执行时间
- 用Java测试网络代码
- Java连接oracle测试代码
- java连接mysql 测试代码
- java里测试时间代码
- Java中测试代码执行时间
- 红帽子Red Hat Linux 9光盘启动安装过程
- 新技术的市场化发展历程
- Explorer文件菜单添加
- 春笛短信模块的使用说明
- 浅谈Java的输入输出编码
- java测试代码
- 一个qreport的例子:中文多行显示,表格线在多行显示时的扩展,扩展之后的手动分页,文本式的反向报表(试过)
- 国庆值班第一天
- icai项目开发日记(三)
- .NET下基于API封装的DirectUIHWND窗体访问
- .NET中Form之间的互相调用
- .NET中获取电脑名、IP及用户名方法
- 误导程序员的喧嚣:评CSDN引导Java和Ruby之争
- Windows平台下PHP5.0+Mysql4.1.x环境架设(1-6)[转]