Hessian是一个轻量级的remoting on http工具,采用的是Binary RPC协议,所以它很适合于发送二进制数据,同时又具有防火墙穿透能力。Hessian一般是通过Web应用来提供服务,因此非常类似于平时我们用的WebService。只是它不使用SOAP协议,但相比webservice而言更简单、快捷。
Hessian官网:http://hessian.caucho.com/
接下来我们测试一下Hessian的性能
测试类如下:
接口:
package test.hessian;
public interface IHello {
String sayHello(String name);
public TestBean testBean(int i,String j);
public void test(TestBean t);
}
实现:
package test.hessian;
import com.caucho.hessian.server.HessianServlet;
public class HelloImpl extends HessianServlet implements IHello {
private static final long serialVersionUID = 1464625224364842441L;
@Override
public String sayHello(String name) {
return "hello:" + name;
}
@Override
public TestBean testBean(int i, String j) {
TestBean t = new TestBean();
t.setTestInt(i);
t.setTestString(j);
return t;
}
@Override
public void test(TestBean t) {
System.out.println(t);
}
}
TestBean:
package test.hessian;
import java.io.Serializable;
public class TestBean implements Serializable {
private static final long serialVersionUID = 3726175313904115945L;
private int testInt;
private String testString;
private byte[] byteArray = new byte[1024 * 10];
public TestBean() {
}
public TestBean(int testInt, String testString) {
this.testInt = testInt;
this.testString = testString;
}
public int getTestInt() {
return testInt;
}
public void setTestInt(int testInt) {
this.testInt = testInt;
}
public String getTestString() {
return testString;
}
public void setTestString(String testString) {
this.testString = testString;
}
public byte[] getByteArray() {
return byteArray;
}
public void setByteArray(byte[] byteArray) {
this.byteArray = byteArray;
}
}
准备完毕,现在启动服务:
package test.hessian;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
public class ServletContext {
public static void main(String[] args) throws Exception {
Server server = new Server(8080);
ServerConnector connector = new ServerConnector(server);
server.addConnector(connector);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/test");
server.setHandler(context);
context.addServlet(new ServletHolder(new HelloImpl()), "/hello");
server.start();
}
}
到此为止,这个服务的服务器端已经搭建起来了,现在开始用压测程序压测
package test.hessian;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import com.caucho.hessian.client.HessianProxyFactory;
public class StressTest {
private final static String url = "http://127.0.0.1:8080/test/hello";
public static void main(String args[]) throws Throwable {
HessianProxyFactory hpf = new HessianProxyFactory();
hpf.setChunkedPost(false);
final IHello hello = (IHello) hpf.create(IHello.class, url);
// 创建收集信息list
final List<StopWatch> list = new ArrayList<StopWatch>();
//线程数量
int count = 100;
final long start1 = System.currentTimeMillis();
final CyclicBarrier barrier = new CyclicBarrier(count, new Runnable() {
@Override
public void run() {
long end1 = System.currentTimeMillis();
//分析收集到的信息
analyseStopWatch(list, (end1 - start1));
}
});
final Object obj = new Object();
for (int i = 0; i < count; i++) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
for (int j = 0; j < 1000; j++) {
//创建收集信息对象
StopWatch sw = new StopWatch();
long startTime = System.currentTimeMillis();
sw.setStartTime(startTime);
try {
hello.sayHello("" + j);
//TestBean t = hello.testBean(j, j + "");
sw.setStatus(true);
} catch (Throwable e) {
sw.setStatus(false);
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
sw.setEndTime(endTime);
sw.setElapsedTime(endTime - startTime);
//将收集信息对象添加到list中
synchronized (obj) {
list.add(sw);
}
}
} catch (Exception e) {
e.printStackTrace();
}
try {
barrier.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
// if (i < 29) {
// t.setDaemon(true);
// }
t.start();
}
}
private static void analyseStopWatch(List<StopWatch> stopWatchs, long totalSpend) {
Collections.sort(stopWatchs, new Comparator<StopWatch>() {
@Override
public int compare(StopWatch o1, StopWatch o2) {
Long elapsedTime1 = o1.getElapsedTime();
Long elapsedTime2 = o2.getElapsedTime();
return elapsedTime1.compareTo(elapsedTime2);
}
});
int size = stopWatchs.size();
long min = 0;
for (StopWatch sw : stopWatchs) {
if (sw.getElapsedTime() > 0) {
min = sw.getElapsedTime();
break;
}
}
System.out.println("spend time min = " + min + "MS | max = " + stopWatchs.get(size - 1).getElapsedTime() + "MS");
int failCount = 0;
long spendTime = 0L;
for (StopWatch sw : stopWatchs) {
spendTime += sw.getElapsedTime();
if (!sw.isStatus()) {
failCount += 1;
}
}
System.out.println("total spend time = " + totalSpend + "MS");
System.out.println("total request count = " + size);
double d1 = totalSpend;
double d2 = size;
double averageST = d1 / d2;
System.out.println("average spend time = " + spendTime / size + "MS");
System.out.println("Transaction Per Second = " + (1000 / averageST));
System.out.println("total fail count = " + failCount);
}
}
StopWatch :
package test.hessian;
public class StopWatch {
private long startTime;
private long endTime;
private long elapsedTime;
private boolean status;
public StopWatch() {
this.startTime = 0L;
this.endTime = 0L;
this.elapsedTime = 0L;
this.status = false;
}
public long getStartTime() {
return startTime;
}
public void setStartTime(long startTime) {
this.startTime = startTime;
}
public long getEndTime() {
return endTime;
}
public void setEndTime(long endTime) {
this.endTime = endTime;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public long getElapsedTime() {
return elapsedTime;
}
public void setElapsedTime(long elapsedTime) {
this.elapsedTime = elapsedTime;
}
}
开始测试:
1,测试传输数据量为0的性能:
输出:
spend time min = 1MS | max = 153MS (方法执行最小时长最大时长)
total spend time = 27859MS (测试程序运行时间)
total request count = 100000 (请求远程方法次数)
average spend time = 27MS (平均每个方法执行的时间)
Transaction Per Second = 3589.504289457626(每秒方法返回次数)
total fail count = 0 (总共失败次数)
2,测试传输数据量为10K的性能:
private byte[] byteArray = new byte[1024*10];
//hello.sayHello("" + j);
TestBean t = hello.testBean(j, j + "");
输出:
spend time min = 1MS | max = 449MS
total spend time = 39660MS
total request count = 100000
average spend time = 39MS
Transaction Per Second = 2521.4321734745336
total fail count = 0
3,测试传输数据量为1M的性能:
private byte[] byteArray = new byte[1024*1024];
输出:
spend time min = 18MS | max = 3786MS
total spend time = 1712132MS
total request count = 100000
average spend time = 1701MS
Transaction Per Second = 58.406711632047056
total fail count = 0
测试结果:
Hessian调用caucho公司的resin服务器号称是最快的服务器,在java领域有一定的知名度。Hessian做为resin的组成部分,其设计也非常精简高效,实际运行情况也证明了这一点。平均来看,Hessian在少量或中等数据时,表现相当优秀,数据量特别大时,性能稍差。但也很快,Hessian的好处是精简高效,可以跨语言使用,而且协议规范公开,我们可以针对任意语言开发对其协议的实现。目前已有实现的语言有:java, c++, .net, python, ruby。还没有delphi的实现。另外,Hessian与WEB服务器结合非常好,借助WEB服务器的功能,在处理大量用户并发访问时会有很大优势,在资源分配,线程排队,异常处理等方面都可以由成熟的WEB服务器保证。