ConnectionTimeout和SocketTimeout

济南小老虎發表於2024-06-20

ConnectionTimeout和SocketTimeout


背景

最近遇到了很多當機的問題. 
究其原因, 大部分都是資源不釋放導致:
1. 記憶體不釋放導致頻繁FullGC,最終OOM
2. 執行緒不釋放導致執行緒過多,積壓記憶體頁會導致效能下降,當機.
3. 連線池不釋放, 導致新的請求無法獲取資料庫連線,導致無法進行功能處理.
   如果應用伺服器過多,甚至會導致資料庫資源耗盡, 導致嚴重問題. 
4. Redis的鍵值對不過期, 導致鍵值對過多, 引起嚴重效能問題. 
5. 部分功能序列化, 或者是邏輯漏洞導致死迴圈, 長時間佔用CPU,引起卡頓. 

這裡面, 大部分不會導致持久化層的資料庫出問題,
但是連線池洩露比較難處理, 嚴重的情況下會導致資料庫異常.
之前同事的文件裡面提到過資料庫連結的超時設定, 所以想也學習一下相關的內容

JDBC的timeout選項

JDBC的連結url會有多個 timetout的選項
並且不同資料庫url 裡面的單位都不一樣. 
所以這裡只是一個簡單的概述. 並不能作為實際操作推薦. 

JDBC的timeout 應該組要是兩個:
ConnectionTimeout和SocketTimeout

兩者其實是有不同的作用. 
ConnectionTimeout 主要是在建立資料庫連結時生效. 
如果超過這個timeout的時間. 建立連線就會失敗. 

SocketTimeout 針對的是已經建立的連結. 
他會超時時結束連結. 

需要說明: 
ConnectionTimeout 基本上可以無痛的增加配置
但是 
SocketTimeout 如果有慢查詢可能會影響業務執行
不建議隨意的增加.  
不過理論上應該是微服務部署模式. 
制單.稽核等應該可以增加, 如果有慢查詢, 應該需要及時解決. 
BA,大查詢應該設定為0 避免連結被reset 引起問題. 

其他的超時

其實 hikari也有很多超時設定
當然了因為我們公司選用了這個連線池, 很多專案還有用druid的
不一而足. 這裡主要是抄錄一下別人的. 

idleTimeout:用來控制連線在連線池中空閒的時間。
maxLifetime:用來控制連線在連線池中最大的生命週期。


idleTimeout
空閒時間預設設定為600000毫秒(10分鐘)。

配置生效的時機
當minimumIdle小於maximumPoolSize的時候,
HikariCP才開始進行空閒連線的判斷,這個時候idleTimeout引數才會生效。

引數的設定範圍
idleTimeout支援設定的最小值是10000(10秒),
如果設定引數小於10000則會被修改為10000,。
但是此引數允許設定為0,當設定為0的時候表示空閒連線不會從池中被刪除。
但此時並不代表連線不會被移除,連線仍然受到maxLifetime的控制。
而如果引數設定的值大於maxLifetime此引數會被修改為0,連線的存活時間由maxLifetime控制。

maxLifetime
最大的生命週期預設為1800000(30分鐘)。

移除連線
此引數控制連線的最大生命週期,
但是其並不會移除使用中的連線,只有在關閉後連線才會被移除。
同時為了避免同一時間大量連線被移除,HikariCP會給連線設定一個負衰減值。

引數的設定範圍
此引數支援的最小值是30000(30秒),如果設定的引數小於30000,
則會被修改為預設值。此引數也支援設定為0,如果設定為0則標識連線不會因為存活時間被刪除。

maxLifetime設定多長
在實際應用中,資料庫連線可能受到多種因素的影響,
高可用、負載均衡、防火牆以及資料庫本身的配置的影響。
預設值設定為30分鐘是考慮到大多數的元件中都會設定30分鐘為連線的上限。
在實際的應用中有可能需要結合實際進行配置。比如有些專案中明明沒有到達30分鐘但是專案卻丟擲
No operations allowed after connection closed. 異常,
這是因為maxLifetime設定的時間超過了當前資料庫的wait_timeout配置。
當連線存活時間超過其設定的wait_timeout時資料庫會將連線關閉,
而對於HikariCP來說此連線仍然存活然後使用此連線進行資料操作。
所以在具體設定maxLifetime引數的時候可以根據其資料庫中的wait_timeout配置來決定,
可以將maxLifetime設定引數略低於資料庫中的配置,這樣可以HikariCP在資料庫斷開連線前就已經終止連線。

相關文章