SpringBoot druid 踩坑筆記
這是一個同事碰到的案例。
現象
SpringBoot 應用卡死、無反應。
處理過程
1、 匯出執行緒棧,發現 Tomcat 處理執行緒都阻塞在獲取連線上,從棧上看連線池使用的是 druid。
2、 對照 druid 原始碼,發現執行緒一直被阻塞是因為沒有設定獲取連線的超時時間。而從配置來看是有設定的。被阻塞的執行緒棧如下:
"http-nio-8006-exec-200" #7057 daemon prio=5 os_prio=0 tid=0x00007fc82c0a3800 nid=0x1b99 waiting on condition [0x00007fc7c9a57000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for<0x00000000c2923bd8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) at com.alibaba.druid.pool.DruidDataSource.takeLast(DruidDataSource.java:1444) at com.alibaba.druid.pool.DruidDataSource.getConnectionInternal(DruidDataSource.java:1088) at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:953) at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4544) at com.alibaba.druid.filter.stat.StatFilter.dataSource_getConnection(StatFilter.java:661) at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4540) at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:931) at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:923) at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:100)
3、 通過記憶體 dump 發現,druid 連線池除 連線串、使用者名稱、密碼等幾個屬性之外的屬性都是預設值。
此時連線池裡總共有8個連線,都是空閒的,卻沒有執行緒能獲取到連線,都在阻塞、沒有被喚醒。網上查了下,應該是 druid 的bug。
4、 再檢視 druid-spring-boot-starter 原始碼,發現上面幾個屬性的字首是 spring.datasource
,其他屬性的字首是 spring.datasource.druid
。
druid-spring-boot-starter 關於配置的舉例
spring.datasource.url= spring.datasource.username= spring.datasource.password= # Druid 資料來源配置,繼承spring.datasource.* 配置,相同則覆蓋 spring.datasource.druid.initial-size=5 spring.datasource.druid.max-active=5
5、 這個應用的另一個問題是,他們對每個請求進行攔截校驗簽名,簽名的祕鑰資訊是存在資料庫裡,處理過程為:1. 從資料庫取祕鑰資訊,2. 進行加解密並校驗。開發人員把整個過程放在一個只讀事務裡。其實他這個加解密是比較耗時的,由於有事務,資料庫連線只能在事務結束時才釋放。這就降低了連線使用效率。
本人負責的專案,由於使用了 Apollo,為了驗證實時重新整理配置,有檢查每個配置項的值、且採用的 HikariCP ,未踩中這個問題。
歡迎關注我的微信公眾號: coderbee筆記 ,可以更及時回覆你的討論。
