一次 Druid 連接池泄露引發的血案!


最近某個應用程序老是卡,需要重啟才能解決問題,導致被各種投訴,排查問題是 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)
	...

這個配置項雖然可用於排查連接池釋放問題,但生產環境小心使用,如果有的業務執行事務的時間比較長,會被誤回收,小心引發另外一個血案。

推薦去我的博客閱讀更多:

1.Java JVM、集合、多線程、新特性系列教程

2.Spring MVC、Spring Boot、Spring Cloud 系列教程

3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程

4.Java、后端、架構、阿里巴巴等大廠最新面試題

生活很美好,明天見~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM