close_wait过多服务器无响应,记一次大量CLOSE_WAIT连接导致的服务宕机
最近線上服務出現了一段時間的無法響應,在此總結一下問題的排查過程。
監控信息
監控顯示CPU和內存沒有異常波動,TCP連接中有大量的CLOSE_WAIT狀態的連接。
看一下TCP連接斷開的過程:
也就是說客戶端發起了斷開連接的包,服務端收到數據后狀態變更為CLOSE_WAIT,這時需要等待服務端處理完連接中未發送完的數據之后發送FIN給客戶端,但是服務端此時可能因為各種原因,中斷在了這個環節,導致操作系統的連接數被CLOSE_WAIT占用,沒有足夠資源響應客戶端請求。所以接下來就需要查清楚服務端到底在忙什么,為什么不繼續完成斷開連接的四次揮手過程。
線程棧
對于Java應用,可以利用JDK提供的工具查看線程的棧。
jstack -l pid
其中pid是JVM進程的ID
打印出的棧信息中可以發現大量類似上圖的WAITING狀態的線程,線程在以下幾種情況會進入WAITING狀態:
Object的wait方法,并且沒有使用timeout參數;
Thread的join方法,沒有使用timeout參數;
LockSupport的park方法。
如果一個線程調用了一個對象的wait方法,那么這個線程就會處于waiting狀態直到另外一個線程調用這個對象的notify或者notifyAll方法后才會解除這個狀態。
具體到此處的問題,可以理解為數據庫連接池中獲取連接時,沒有可用連接,此時調用notEmpty.await();等待有連接釋放回收到連接池或創建新的連接后notify當前線程再來獲取連接。所以此時問題的根本原因是數據庫連接池耗盡,一直在wait可用連接,線程無法繼續執行下去。
數據庫連接池的配置
我的應用是基于springboot開發的,在技術社區也查到了一些關于springboot的默認數據庫連接配置可能會存在潛在風險。數據連接池默認配置帶來的坑
簡單來說,默認的數據連接配置,可能會導致連接池中的連接是不可用的,但是仍在連接池中充數,并不會被釋放。增加了以下幾個參數,DONE!
testWhileIdle: true
validationQuery: SELECT 1
timeBetweenEvictionRunsMillis: 60000
總結
以上是生活随笔為你收集整理的close_wait过多服务器无响应,记一次大量CLOSE_WAIT连接导致的服务宕机的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python接口测试实战_Python接
- 下一篇: java读取空格_java 读取文件路径