我现在在调用远程服务器上部署的EJB的时候,有时候因为网络或者其他原因,所以非常慢,很长时间也不能够返回结果,我不知道可不可以设置一个超时控制这样的东东,如果在一段时间内没有返回结果,我就直接返回,执行忙下边的程序。谢谢大家了,请大家多帮忙!
注:EJB2.0 中 sessinoBean
注:EJB2.0 中 sessinoBean
解决方案 »
- 启动tomcat报错:Source not found for URLClassLoader$1.run() line: not available
- hibernate的头痛问题,高手请帮帮我
- 鼠标点击传值
- 关于Openfire插件开发的问题,紧急求助!
- java数组问题,请大家帮忙
- 请大家讲解一下一个单独的功能模块如何调用工作流?
- 在JAVA中使用transform操纵XSLT报错: RuntimeStub::init_check_patching Runtime1 stub
- 请问jakarta的官方网站里,有关于Tomcat、Servlet配置方面的介绍吗?
- 用j2ee开发workflow的朋友,留下个联系方式,大家一起进步!!!
- java调用C++酒店电子门锁(门禁)接口函数调用
- socket服务端计算客户端传进的两个数的和并返回给客户端
- webservice 错误
目前在网络开局现场发现每接入一个Client会导致30-40服务器线程的增加。按照50个Client计算,则可能增加2000个左右的线程。而这些线程可能会占用1M做的stack内存,而通常Java的堆内存分配的比较多,最后导致无法创建本地线程的问题。
通过观察现场的线程,发现绝大多数是RMI的通讯线程
4.2 问题分析
客户端到服务器的通信目前存在两种主要的通信方式:F口发起的调用和JMS的异步消息上班。其中F口的调用是RMI方式的EJB调用。而JMS的异步消息也是通过RMI的主动轮询来完成的。
并且在进行F口调用的时候,会在应用逻辑中有可能产生新的线程。这些线程的数量也是需要关注的。
4.3 实现原理
客户端和服务器频繁的发起RMI调用,导致服务器上会有很多线程为这些通讯连接服务。由于RMI调用通常都是短时的,比如JMS的消息主题的轮询,是每2s进行一次,但是每次调用的时间是在毫秒级。控制调用的并发程度,对性能没有什么损失,就能降低服务器上的接入线程的数量。
4.3.1 JMS并发控制
并发控制的出发点是:一个RMI调用通常在非常短的时间完成。目前2秒钟轮询一次,理论上可以支持非常多的主题轮询。目前网管系统中出现很多JMS相关的线程,是由于并发度导致的,而非处理能力上问题。即很多请求是在同一个时刻发起导致了很多线程,如果将请求错开一点,也是完全能够满足要求,并不会带来性能上的损失。
并发控制的原理是:控制并发的数量,将请求均匀分布。
基本实现方法是在请求的时候进行排队。如原来会多线程并行的调用如下的方法,
SpyMessage message = serverIL.receiveAndAck(connectionToken,
sub.subscriptionId, wait);
每个方法很快会返回,每隔2s会调用一次,通过如下的方法就可以控制并发度,也就可以控制在服务器上的线程数量,
concurrentSepephore.acquire();
SpyMessage message = serverIL.receiveAndAck(connectionToken,
sub.subscriptionId, wait);
concurrentSepephore.release();
注意:网络不好的时候,会导致在获取资源锁的时候有较大的延时。但是这个延时即使在没有采取资源锁的情况下也是应该有的。导致问题的关键是网络不好,即使全并发延时也会相同的严重。
4.3.2 F口调用并发控制
F口的并发程度不高。为了控制异常冲高的情况,并且为了控制服务器上接入线程的数量,因此也进行相同的并发控制。主要是在F口的EJB调用上进行并发控制。
4.3.3 端口合并
UEP在deploy-default.properties中配置了很多的RMI端口,这些端口使用了不同RMIClientSocketFactory。使用不同的RMIClientSocketFactory,但是对超时值设置却是相同的。
这里存在的问题:
1、 使用不同的端口,导致建立的不同TCP连接,会导致服务器上存在不同的线程来服务。导致服务器端频繁的创建和销毁线程。
2、 端口分开没有体现应有的作用。首先设置的超时值大部分是相同的。即使不同,实质差别也不大。
3、 导致穿越防火墙的时候开了过多的端口。
解决办法
将常用的RMI端口进行合并。
目前经常发起的RMI调用有:F口调用,F口的心跳,JNDI的lookup。
jndi.rmiobjectport=21104
jndi.rmiport=21102
uep.finterface.heartbeart.Port=21108
现状:
JNDI的超时
jndi.rmiConnTimeout=600000
jndi.rmiSoTimeout=600000
F口调用的超时
ums.invoker.rmi.conntimeout=600000
ums.invoker.rmi.sotimeout=600000
F口心跳的超时
long interval = SessionCenter.getHeartBeatInteval();
int count = SessionCenter.getHeartBeatFailCount();
int timeOut = (int)(interval * count / 4);
FITimedRMIClientSocketFactory csf = new FITimedRMIClientSocketFactory();
csf.setTimeout(timeOut, timeOut);
其中缺省的设置是:
uep.finterface.heartbeat_interval=30000
uep.finterface.heartbeat_fail_times=6
折合下来是连接的超时45000,读的超时是45000ms。
可以将这三个端口的超时值设置为一致的。因为都是客户端到服务器发起的调用,面对相同的网络环境。其他端口,如果是RMI的通讯方式,也是可以按照类似方式合并的。目前合并这三个端口,主要是为了减少服务器端的线程考虑的。
修改方法
RMI要共享端口,需要使用相同的RMIClientSocketFactory实现或者都不使用。建议都不使用。
修改步骤:
1、 修改F口心跳
修改FIInitManager中初始化HeartbeatReciever代码,
hearbeatReciever = new HeartbeatReciever(port,csf);
修改为
hearbeatReciever = new HeartbeatReciever(port,null);
2、 修改JNDI
修改ums-svr\kernel\server\default\conf\all\jboss-service.xml.tmpl中的
<mbean code="com.zte.ums.uep.psl.naming.server.GlobeNamingServerMain"
name="zte:service=GlobeNamingServer">
<attribute name="Port">@port@</attribute>
<attribute name="RmiPort">@rmiport@</attribute>
<attribute name="RmiConnTimeout">@rmiConnTimeout@</attribute>
<attribute name="RmiSoTimeout">@rmiSoTimeout@</attribute>
<attribute name="ClientSocketFactory">com.zte.ums.uep.psl.naming.interfaces.TimedRMIClientSocketFactory</attribute>
<!--<attribute name="ServerSocketFactory">custom</attribute>-->
</mbean>
注释掉其中的ClientSocketFactory属性。
3、 修改F口调用
修改ums-svr\kernel\server\default\conf\all\jboss-service.xml.tmpl中的
<mbean code="org.jboss.invocation.jrmp.server.JRMPInvoker"
name="jboss:service=invoker,type=jrmp">
<attribute name="RMIObjectPort">@rmiobjectport@</attribute>
<attribute name="RMIClientSocketFactory">com.zte.ums.uep.psl.systemsupport.rmisocketfactory.JRMPRMIClientSocketFactory</attribute>
<!--<attribute name="RMIServerSocketFactory">custom</attribute>
<attribute name="RMIServerSocketAddr">custom</attribute>
-->
</mbean>
注释掉其中的RMIClientSocketFactory属性。修改deploy-default.properties文件
uep.finterface.heartbeart.Port=21108
jndi.rmiport=21102
jndi.rmiobjectport=21104
都修改成21104即可。
增加系统属性:
//客户端超时,可只在客户端设置
sun.rmi.transport.connectionTimeout=300000//客户端idle timeout,5分钟
sun.rmi.transport.tcp.responseTimeout=600000//客户端,保持和目前相同。
//服务器超时,可只在服务器设置
sun.rmi.transport.tcp.readTimeout= 600 * 1000//服务端,保持和目前相同