DBCP用了有一段时间了,在并发相对较大的情况下也没出现过什么问题,至少能满足现网系统的要求。就在不久之前,遇到了一个怪异的问题:
启动应用,能访问数据库,但过了一段时间,约两个小时左右,系统就出现访问“卡住”的现象,用网页打开,不停的处于加载状态,就是加载不出来。
通过测试,就定位到了链接数据库出现问题了,因为都是运行一段时间就出现“卡死”状态,通过以前的经验立刻判断,会不会是因为某个线程吊死了,所以接下来的线程全部卡在这里了,因为这个DBCP用了也有一段时间了,觉得他的问题不大,如果有问题的话应该早就出现了。所以开始就从代码入手。经过详细的排查和测试,也发现不了代码有什么问题,几乎吧所有复杂或有干扰的代码都去掉了,还是会出现这个问题,通过查看日志,也没发现有报错现象,那就纳闷了,有问题,但又不报错,怎么回事。
再后来,我坚信是DBCP的问题, 回想起以前查DBCP资料的时候,有看到说关于DBCP有bug的问题,我心想难道是这个问题导致?我立刻搜索相关资源,也没什么特别明确的资料,因为系统没有报错信息。因为系统快要上线了,这个问题解决不了,我想觉肯定睡不好,于是我被这个问题降低了我的睡眠质量。第二天,我进一步详细的排查了日志信息,发现了昨晚链接数据库的报错信息:java.sql.SQLException: Io 异常: 连接超时。
ohmy god,难道数据库问题,没可能,我昨晚排除了数据库服务器问题,在仔细检查日志信息,发现空闲链接是有的,为什么就不能连呢。再发现今天能连接数据库了,再看日志,空闲数0和1之间徘徊,开始有点头绪了,带着疑问google和百度了一下,再结合自己的测试,原来是这样:程序启动的时候新建立的数据源没有用,过了数据库的超时时间,就获取不到真正的连接了,就在那死等超时。也是因为没有对DBCP了解透切,所以以前在配置的时候直接大概能用就行,而且用了那么长的一段时间没有问题,就更加肯定这个配置的信息。之前的系统没有问题,是因为系统24小时总有人访问,而且量不小,所以连接池的连接总是在使用,没有超过数据库的会话链接超时时间,并且连接数一超过了空闲数,就是重新获取新链接,就算空闲的访问不了,新的一样会访问。那个无效的链接只是在等超时而已,其实问题已经存在,只不过自己没有注意而已。幸好问题发现了,让我对这DBCP有了更深的认识。
后来的处理就是多加了TestWhileIdle、TimeBetweenEvictionRunsMillis、NumTestsPerEvictionRun、MinEvictableIdleTimeMillis等参数进行了调优,大概就是多加了DBCP的监控线程,让他检查数据源连接的有效性,而且还要结合自身数据库等环境进行配置。
具体的配置参数可以参考一下链接:
http://agapple.iteye.com/blog/791943
http://www.blogjava.net/aoxj/archive/2008/02/19/180704.html
最后要提醒一下自己:别浮躁,要细心。