一次 Druid 连接池泄露引发的血案!
程序员文章站
2022-05-29 13:17:36
最近某个应用程序老是卡,需要重启才能解决问题,导致被各种投诉,排查问题是 Druid 连接池泄露引发的血案。。 异常日志如下: 连接池中的连接数量已经到达最大值了,到了 60 秒还不能创建连接就超时报错了。 问题很明显,肯定是应用程序哪里用了连接但没有释放,全局排查代码又比较艰难,加了三个 Drui ......
最近某个应用程序老是卡,需要重启才能解决问题,导致被各种投诉,排查问题是 druid 连接池泄露引发的血案。。
异常日志如下:
error - com.alibaba.druid.pool.getconnectiontimeoutexception: wait millis 60000, active 50, maxactive 50, creating 0 at com.alibaba.druid.pool.druiddatasource.getconnectioninternal(druiddatasource.java:1512) at com.alibaba.druid.pool.druiddatasource.getconnectiondirect(druiddatasource.java:1255) at com.alibaba.druid.filter.filterchainimpl.datasource_connect(filterchainimpl.java:5007) at com.alibaba.druid.filter.stat.statfilter.datasource_getconnection(statfilter.java:680) at com.alibaba.druid.filter.filterchainimpl.datasource_connect(filterchainimpl.java:5003) at com.alibaba.druid.pool.druiddatasource.getconnection(druiddatasource.java:1233) at com.alibaba.druid.pool.druiddatasource.getconnection(druiddatasource.java:1225) at com.alibaba.druid.pool.druiddatasource.getconnection(druiddatasource.java:90)
连接池中的连接数量已经到达最大值了,到了 60 秒还不能创建连接就超时报错了。
问题很明显,肯定是应用程序哪里用了连接但没有释放,全局排查代码又比较艰难,加了三个 druid 连接池配置项,最终定位并解决了问题。
添加以下配置:
<!-- 是否打开强制回收连接功能 --> <property name="removeabandoned" value="true" /> <!-- 超时时间,单位:毫秒 --> <property name="removeabandonedtimeoutmillis" value="600000"/> <!-- 连接回收时是否记录日志 --> <property name="logabandoned" value="true" />
这就是连接泄露配置项,如果连接长时间不归还,removeabandoned
打开状态,超过 removeabandonedtimeoutmillis
设置的超时时间,将会强制回收连接。
连接池初始化时会启动一个线程,用于检查并回收连接。
参考源码:
com.alibaba.druid.pool.druiddatasource#createandstartdestroythread
当 logabandoned
打开状态时,关闭连接同时会记录当时的堆栈日志,可用于定位到哪些代码打开了连接没关闭。
abandon connection, owner thread: https-jsse-nio-4443-exec-9, connected at : 1573521883837, open stacktrace at java.lang.thread.getstacktrace(thread.java:1589) at com.alibaba.druid.pool.druiddatasource.getconnectiondirect(druiddatasource.java:1305) at com.alibaba.druid.filter.filterchainimpl.datasource_connect(filterchainimpl.java:4619) at com.alibaba.druid.filter.stat.statfilter.datasource_getconnection(statfilter.java:680) at com.alibaba.druid.filter.filterchainimpl.datasource_connect(filterchainimpl.java:4615) at com.alibaba.druid.pool.druiddatasource.getconnection(druiddatasource.java:1225) at com.alibaba.druid.pool.druiddatasource.getconnection(druiddatasource.java:1217) at com.alibaba.druid.pool.druiddatasource.getconnection(druiddatasource.java:90) at org.springframework.jdbc.datasource.lookup.abstractroutingdatasource.getconnection(abstractroutingdatasource.java:162) ...
这个配置项虽然可用于排查连接池释放问题,但生产环境小心使用,如果有的业务执行事务的时间比较长,会被误回收,小心引发另外一个血案。
推荐去我的博客阅读更多:
2.spring mvc、spring boot、spring cloud 系列教程
3.maven、git、eclipse、intellij idea 系列工具教程
生活很美好,明天见~