忙乎了将近两周,终于搞定了。从一开始怀疑是网络的问题,后来觉得不是,可能是应用的问题,发现很可能是数据库的问题,最后真相大白又回到原点,原来是网络防火墙在捣鬼。行为非常诡异,怎么想也想不明白,我都没多少信心准备放弃了,没想到原因竟然如此简单。
事情是这样的,我们开发的系统需要保持和Oracle数据库的持续连接,如果因为网络或者其它原因非正常断开的话,必须重新启动应用程序,否则将会出错无法使用。在测试环境运行很稳定,一搬到机房机架上就出现奇怪的现象,第二天早上来看服务器,所有的数据库连接都断掉了,有时候白天也断,而且一个应用断的次数特别频繁,其它应用白天不怎么断。因为我们的应用服务器网段是192.168.x.x,而数据库服务器在10.x.x.x网段,刚开始我怀疑是中间的路由器有这种问题,如果网络持续一段时间没有流量自动把网络断开。并且和网管说了这事,他说不可能有这种问题。因为我们以前做过另外一个系统也存在这种问题,好像是这个原因,不过后来怎么解决的不是很清楚了。找知情人士了解后原来是数据库网卡的原因,从应用服务器ping数据库服务器一个晚上有几次丢包现象,换数据库服务器网卡就没事了。
于是我们用ping -t server-IP > ping.txt 来检查网络是否有丢包现象,持续几个晚上都没有一次丢包的,网络状况非常好。我检查网卡属性的电源属性卡上有一个复选框是否允许计算机闲置时关闭该设备,默认是选中的。于是我怀疑是网卡被计算机关掉了,于是所有连接均断开了,但是白天之断开一个解释不同啊。应用程序有问题?为什么测试环境中没发现问题?有可能是某一块数据有问题,他们测试时乱调图碰到雷区了,于是我检查所有的数据,没有那种问题。真是让人费解,而且我持续ping,网卡也不可能被关闭的啊。
有可能是某个端口关闭了,于是我们写了一个小程序,打开一个数据库连接,每隔一定时间查一下数据库,保持端口是打开的。问题依旧存在,这个小程序的连接没断,其它的全断了。
是什么原因呢?其实现在想起来问题已经很明朗了,但是当时就是不明白怎么回事。而且那天老是打电话过来,连接又断了,上午断两次,下午又断了两次。一整天我们都没想出什么好办法,怎么会这么变态,为什么会只断掉一个?我当时怀疑是我们应用程序有点问题,在绞尽脑汁想办法怎么检测应用程序的错误。
为了检测断开的规律,我写了两个触发器,用户登陆时网一个表中插入一条记录,注销是把注销时间填入表中。后来发现根本一点用也没有,非正常退出时根本不会触发LOGOFF事件,白忙乎了!
下班了,骑车回家,突然想到一个办法,定时激活连接,保持活动状态看它还断不断。很多好的想法都是在我离开办公室回家的路上想出来了,在办公室怎么想也想不出来,离开办公室就想出了。第二天马上行动,果真有效,连接没有再断过。但是这样不是个办法,为什么连接一段时间不活动就会被杀掉了呢?在我们的应用程序中看不到原因,只是说连接丢失,在sqlplus中提示说end-of-file communication channel。
今天一整天我都在网上狂找相关内容,oracle connection lost, oracle session lost,oracle session timeout等等,看到也有人碰到类似我这种情况的人,但是没有好的办法。我把Oracle net service得文档翻了一遍,看到sqlnet.ora有一个关于超时的参数SQLNET.EXPIRE_TIME简直如获至宝,后来发现原来没用。服务器端自动杀掉客户端进程的情况还可以通过Profile来实现,限制IDLE_TIME,但是我检查数据库根本没有相关的设置。
好不容易找到一溜很长的帖子,也是关于我这种问题的,最后他说解决了是防火墙的问题。但是以前我印象中防火墙只是针对端口的,怎么会保持某些活动连接,杀掉不活动的连接呢?后来我去网上查了查防火前的有关原理,好象它能处理到TCP/IP连接一级,也就是可以只断开某一个不活动的连接。但我还是不很确定,但是我知道在数据库服务器和应用服务器之间有防火墙,把机器搬过去的那天,能ping通数据库服务器,但是不能连数据库,后来网管把Oracle数据库的两个端口打开就可以了。
我们找到网管,他说是有这种问题,防火墙就是这样的,如果一个连接长时间不活动就会自动杀掉的。如果不这样的话,防火墙的内存很快会用完,还说我们违背了TCP/IP的设计原则。但是没办法,我们的应用程序需要持续而稳定数据库连接,只能把我们的应用服务器放到防火墙后面去。于是他把我们的服务器跳了线,变成一个网段的,从此不再有连接断开的问题了。终于彻底解决这个问题,长舒一口气!!!
其实主要原因还是网络规划有问题,怎么能把我们应用服务器和数据库服务器隔开呢?