问题终于找到,简单的说是因为java 序列化的效率低下,而ejb调用之间又大量使用序列化,因此造成极大的性能消耗,而且也影响到响应时间。仔细分析了一下项目情况,呵呵,情况非常严重,系统架构是按照三层来设计的,每个层都是ejb,调下一层都是通过远程接口,而且层之间可能还多个ejb的调用。
(说句题外话,这种设计个人感觉非常,恩,不理解,性能杀手,而且ejb配置极其复杂,当然或者ejb本来就是如此,ebj和weblogic对我来说是很陌生很高深的东西,目前还没有深入掌握。)
很自然的会想到ejb2.0中的配置项enable-call-by-reference,如果能够开启就可以避免远程接口调用中的序列化。检查配置文件发现几乎能设置enable-call-by-reference的地方都设置为true了,奇
怪,再检查部署方式时发现,恩,晕倒,被部署到不同的ear包中了。
不同的ear包,enable-call-by-reference就算设置位true也开启不了吧?
接下来的改进方式,很自然就想到,如果能打包到同一个ear中,就可以在不改动代码,不改动部署文件的情况下解决这个问题,似乎是一个不错的好想法。
谨慎起见,同时为了拿到足够的证据来说法上层,先做个试验先。
模拟公司的项目结构,单独写了一个project,1个servlet负责接受外界请求,3个SLSB模拟三层工作,ejb直接只提供远程接口,然后打包到同一个ear包进行测试。当然enable-call-by-reference设置为true
和false来进行对比测试。
为了突出这个差异,ejb中都不进行任何操作,也不sleep。这样消耗就主要体现在java 序列化的消耗上,而且为了模拟真实情况,参数设置的比较大,里面放了1000个instance。
使用loadrunner,开启100个测试线程,通过http访问servlet,测试时间一分钟,看能执行多少次请求,测试结果如下:
enable-call-by-reference = false : 558
enable-call-by-reference = true : 21163
由于这个结果的差异性实在是太大了,因此没有必要进行多次测试,近40倍的差异完全可以反应问题了,当时实际项目中应该远没有这么夸张。
总结一下:
1. java serialize 非常慢
2. enable-call-by-reference可以有效避免这个开销
因此,能enable-call-by-reference就尽量enable-call-by-reference。
ps:顺便将这个测试的eclipse project也分享出来吧,请在这里下载
http://www.fs2you.com/files/045b367d-5d23-11dd-a2ed-0014221b798a/