Rev 1127 | Blame | Compare with Previous | Last modification | View Log | RSS feed
package ak.httpbench;
import java.util.List;
import java.util.ArrayList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
public class HttpBench
{
private static Log log = LogFactory.getLog(HttpBench.class);
public static void main(String[] args)
throws Exception
{
HttpBench hb = new HttpBench();
if(hb.parseParams(args))
hb.run();
}
// config
private int threadNumber = 10;
private int requestNumber = 50;
private int requestPerConnection = 0;
private int sleepMin = 0;
private int sleepMax = 1000; // 1s
private int timeout = 60000; // 1min
private String firstUrl = null;
private List urls = new ArrayList();
private int parseInt(String s, String prefix, String errorMsg)
throws Exception
{
try {
return Integer.parseInt(s.substring(prefix.length()));
}
catch(Exception ex) {
log.error(errorMsg);
throw ex;
}
}
private boolean parseParams(String[] args)
throws Exception
{
try {
for(int i = 0; i< args.length; i++) {
String s = args[i];
if(s.startsWith("thr=")) {
threadNumber = parseInt(s, "thr=",
"Cannot get number of threads from " + s);
}
else if(s.startsWith("req=")) {
requestNumber = parseInt(s, "req=",
"Cannot get number of requests from " + s);
}
else if(s.startsWith("rpc=")) {
requestPerConnection = parseInt(s, "rpc=",
"Cannot get number of requests per connection from " + s);
}
else if(s.startsWith("sleepMin=")) {
sleepMin = parseInt(s, "sleepMin=",
"Cannot get min sleep from " + s);
}
else if(s.startsWith("timeout=")) {
timeout = parseInt(s, "timeout=",
"Cannot get timeout from " + s);
}
else if(s.startsWith("sleepMax=")) {
sleepMax = parseInt(s, "sleepMax=",
"Cannot get max sleep from " + s);
}
else if(s.startsWith("firstUrl=")) {
firstUrl = s.substring("firstUrl=".length());
if(firstUrl.equals("")) firstUrl = null;
}
else {
urls.add(s);
}
}
if(urls.isEmpty()) {
log.error("Need at least one URL to work");
return false;
}
return true;
}
catch(Exception ex) {
return false;
}
}
private void run()
throws Exception
{
log.info("start " + threadNumber + "/" + requestNumber + "/" + requestPerConnection
+ " " + sleepMin + "/" + sleepMax);
log.info(" firstUrl: " + (firstUrl == null ? "<null>" : firstUrl));
for(int i = 0; i < urls.size(); i++)
log.info(" url: " + urls.get(i));
List threads = new ArrayList();
List workers = new ArrayList();
String[] urlArray = (String[])urls.toArray(new String[] {});
for(int i = 0; i < threadNumber; i++) {
log.debug("create thread " + i);
HttpThread ht = new HttpThread(firstUrl, urlArray);
workers.add(ht);
ht.setRequestNumber(requestNumber);
ht.setRequestPerConnection(requestPerConnection);
ht.setSleepMin(sleepMin);
ht.setSleepMax(sleepMax);
ht.setTimeout(timeout);
Thread t = new Thread(ht);
threads.add(t);
t.start();
}
// wait for all
for(int i = 0; i < threads.size(); i++) {
log.debug("wait for thread " + i);
Thread t = (Thread)threads.get(i);
try {
t.join();
}
catch(InterruptedException ex) {
}
}
// statistics
long totalTime = 0;
long reqTime = 0;
long minTime = Long.MAX_VALUE;
long maxTime = -1;
int successRequest = 0;
int failRequest = 0;
for(int i = 0; i < workers.size(); i++) {
HttpThread ht = (HttpThread)workers.get(i);
if(ht.getSuccess()) {
totalTime += ht.getRunTime();
List results = ht.getResults();
for(int j = 0; j < results.size(); j++) {
RequestResult r = (RequestResult)results.get(j);
totalTime -= r.sleepBefore;
if(r.success) {
successRequest++;
long t = r.stopTime - r.startTime;
reqTime += t;
if(minTime > t) minTime = t;
if(maxTime < t) maxTime = t;
}
else {
failRequest++;
}
}
}
}
log.info("done " + totalTime + "ms / " + successRequest + " = "
+ (totalTime / successRequest) + "ms "
+ minTime + "/" + (reqTime / successRequest) + "/" + maxTime
+ " ms, " + failRequest + " failed");
}
}
class RequestResult
{
public boolean success = false;
public String url;
public long sleepBefore;
public long startTime;
public long stopTime;
public int code;
public Exception exception;
}
class HttpThread implements Runnable
{
private static int threadCount = 0;
private static Log log = LogFactory.getLog(HttpThread.class);
private int id;
private String firstUrl; // is used one time only, may be null
private String[] urls;
private int requestNumber = 1;
private int requestPerConnection = 0; // 0 == all
private int sleepMin = 0;
private int sleepMax = 0;
private int timeout = 0;
private boolean success;
private long runTime;
private List results;
public HttpThread(String firstUrl, String[] urls)
{
id = threadCount++;
this.firstUrl = firstUrl;
this.urls = urls;
}
public int getId()
{
return id;
}
public int getRequestNumber()
{
return requestNumber;
}
public void setRequestNumber(int requestNumber)
{
this.requestNumber = requestNumber;
}
public int getRequestPerConnection()
{
return requestPerConnection;
}
public void setRequestPerConnection(int requestPerConnection)
{
this.requestPerConnection = requestPerConnection;
}
public void setSleepMin(int sleepMin)
{
this.sleepMin = sleepMin;
}
public int getSleepMax()
{
return sleepMax;
}
public void setSleepMax(int sleepMax)
{
this.sleepMax = sleepMax;
}
public int getTimeout()
{
return timeout;
}
public void setTimeout(int timeout)
{
this.timeout = timeout;
}
public boolean getSuccess()
{
return success;
}
public long getRunTime()
{
return runTime;
}
public List getResults()
{
return results;
}
public void run()
{
long sumSleep = 0;
log.info(Integer.toString(id) + ": start");
try {
HttpClient client = new HttpClient();
results = new ArrayList();
for(int i = 0; i < requestNumber; i++) {
results.add(new RequestResult());
}
long startTime = System.currentTimeMillis();
for(int i = 0; i < requestNumber; i++) {
RequestResult result = (RequestResult)results.get(i);
if(sleepMax > 0) {
long sleep = (long)(Math.random() * (sleepMax - sleepMin)) + sleepMin;
sumSleep += sleep;
result.sleepBefore = sleep;
log.trace(Integer.toString(id) + ": sleep for " + sleep + "ms");
Thread.sleep(sleep);
}
if(i == 0 && firstUrl != null)
result.url = firstUrl;
else
result.url = urls[(firstUrl == null ? i : i-1) % urls.length];
GetMethod get = new GetMethod(result.url);
get.getParams().setSoTimeout(timeout);
try {
result.startTime = System.currentTimeMillis();
result.code = client.executeMethod(get);
result.stopTime = System.currentTimeMillis();
result.success = true;
if(log.isTraceEnabled()) {
String response = get.getResponseBodyAsString();
log.trace(Integer.toString(id) + ": got " + result
+ " in " + (result.stopTime - result.startTime)
+ "ms \n'" + response.substring(0, 100) + "'");
}
else if(log.isDebugEnabled()) {
log.debug(Integer.toString(id) + ": got " + result
+ " in " + (result.stopTime - result.startTime) + "ms");
}
}
catch(Exception ex) {
result.stopTime = System.currentTimeMillis();
result.exception = ex;
}
finally {
get.releaseConnection();
}
if(requestPerConnection > 0 && (i+1) % requestPerConnection == 0
&& i < requestNumber-1)
{
log.debug(Integer.toString(id)
+ ": request per connection limit reached at " + i);
client.getHttpConnectionManager().closeIdleConnections(0);
}
}
client.getHttpConnectionManager().closeIdleConnections(0);
success = true;
runTime = System.currentTimeMillis() - startTime;
}
catch(Exception ex) {
success = false;
log.warn(Integer.toString(id), ex);
}
log.info(Integer.toString(id) + ": done" + (success ? " " + runTime
+ "/" + sumSleep + "/" + (runTime - sumSleep) + " ms": " with error"));
}
}