Druid連接池參數maxWait配置錯誤引發的問題
1. 背景
數據庫服務器(服務部署在客戶內網環境)的運行一段時間后,網卡出現了問題,導致所有服務都連接不上數據庫,客戶把網絡恢復之后,反饋有個服務還是訪問異常。
2.問題定位
查看異常服務的日志,發現當時的日志打印出了大量的Too many open files,日志表明當時該進程打開的文件句柄數已達到上限,該進程已經不能自動恢復對數據庫的訪問。
通過命令ulimit -a查看配置,確認服務器配置沒有問題。
使用jstack命令查看當時線程的信息,發現大量獲取數據庫連接的線程處於BLOCKED狀態。
從線程堆棧信息發現,線程是從Druid連接池獲取連接的,於是查看DruidDataSource獲取連接的方法,發現有個maxWait參數(默認配置為-1)
查看項目的配置文件,發現有配置spring.datasource.maxWait=60000
通過debug的方式發現改配置沒有生效
3.原因分析
項目是通過spring.datasource.type=com.alibaba.druid.pool.DruidDataSource引入druid連接池,通過這種方式引入配置文件中的其他屬性是無法自動注入。要使該配置生效,可使用javaBean的方式配置。
@Configuration
public class DruidConfig {
@Bean
// 將所有前綴為spring.datasource下的配置項都加載DataSource中
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource() {
return new DruidDataSource();
}
}
關於maxWait的默認值,即如果連接池沒有空閑連接,獲取連接的線程則會一直等待下去。在項目中,在后台有個按時觸發統計的定時任務,定時的向連接池獲取連接,即每個固定時間間隔內就會有一個線程阻塞。數據庫宕機時間一長就會導致,該進程打開的句柄數超過上限。
關於spring.datasource前綴沒有自動注入的原因,可以自行查看springboot 數據源自動注入DataSourceAutoConfiguration類