虚拟账户产品投产之后,观察到这么一个现象:在无人访问应用一段时间之后(应该是两小时左右),再次访问应用时,后台db日志显示一直在opening jdbc connection...,程序卡死,过16分钟之后,程序正常执行,后台db日志显示已经获取到了新的数据库有效连接; 排查过程:起初都不知道16分钟花在何处,哪个函数的调用上;最后还是仔细的根据异常的堆栈信息,看最后执行语句所在位置,再一级级回溯回去,定位到druid源码的位置,加了蛮多的debug日志在里面,才最终定位到JdbcUtils.close(realConnection)执行了16分钟,是jdbc在关闭一个被防火墙drop掉的连接的时候出现了问题,异常信息是IO Exception: broken pipe,是说应用跟oracle服务器之间的连接通道断了。 解决:在stackoverflow上搜索了相关问题,比较确定这个问题确实是由防火墙引起的(一方面oracle服务器不会主动去断开跟应用的连接;另一方面druid我们设置的参数testOnBorrow=true,只会在获取连接的时候进行连接有效性检测,且druid并没有定时探测机制,所以利用排除法确定这个问题是防火墙引起),所以现在有两种解决方案: 在oracle服务器侧加入DCD(Dead Connection Detection)检测,保持连接有效性(但生产环境下不敢随便改基础配置信息); 在druid这一侧加入一个定时检测机制(durid本身没有,需要自己实现一个独立的线程,难点在于我们没办法保证该线程能够与现有druid逻辑完全融合且该线程一直不挂); 在druid基础之上修修补补,应该是可以的,所以我们的解决方案:在获取数据库连接时,先计算当前连接的空闲时间(已设置testWhileIdle=true),当空闲连接超过一小时即调用抛弃连接的函数,且让线程池(开了一个10个大小的线程池)里面的一个线程去做这件事情,主线程继续遍历,直到找到(或者新建)一个有效的连接为止。 (责任编辑:好模板) |