最近做了一个项目,要求一个JMS客户端监听复数台JMS Server,结果在测试时发生了问题。
各机器如下:
JMS Client,简称C
JMS Server1:简称S1
JMS Server2:简称S2
我们发现如果拔掉S1和C之间的网线,结果C和S2之间的连接也断掉了!郁闷啊!~!@#¥%
郁闷中调查了很久,修改了JBOSS的配置,不行!把我们的程序简化,不加任何处理,直接监听JMS,不行!把Spring去掉,直接用代码写监听程序,不行!把Connection中的Security部分去掉,还是不行……
没办法,只好上绝招了,就是,用Debug跟踪代码了,下载了JBOSS的Messaging和Remoting部分的代码,一步一步的跟踪下去,终于找到了问题。
JMS监听是常连接,为了节约Connection资源,所以做了死活管理。JMS Client端会定期去Ping JMS Server。这个定时器是一个Timer;如果一个定时器发现自己所Ping的Server没有应答,就会把自己关闭。
在org.jboss.remoting.LeasePinger里,大家可以看到相关代码!
这段代码没什么问题,但是问题在于这个Timer是静态的。
也就是说,如果这个Timer停止了,那么所有的Ping都没有了。结果就如下:
1.C和S1之间网络故障
2.C停止执行Ping命令的Timer
3.S2收不到C的Ping,就认为C已经停止了对它的监听,回收了和C之间的Connection
4.C不知道发生了问题,还在傻傻的等待S2给它发消息
......