記一次線上服務器oom 排查過程

太長不看版 這篇文章講了啥web

  • 記錄本次oom的排查方法。
  • 一些好用的命令幫助觀察堆,gc等狀態。jmap和jstat。
  • 事故發生的緣由,解決方法和回顧

1: 事故的簡述

某天晚上的21點,業務模塊(微服務)調微信模塊的rpc頻繁超時,接到大量報錯。排查到一半收到以下報警。 堆溢出了。微信模塊機器所有掛掉。spring

2: 開始排查

馬上緊急重啓機器,先保證線上服務可用。而後下載heapdump.hprof文件。須要在jvm啓動的時候加參數纔有dump文件。不然須要使用jmap命令生成。springboot

由於dump是二進制文件須要使用圖形化工具分析。我用的是eclipse memory analyzer。服務器

點擊leak suspects. 看下可能的內存泄漏的點。微信

發現web容器創建了不少連接實例,佔用了很是多內存。 又馬上用jstat -gcutil pid看了下進程gc狀況,fgc觸發了很是屢次,且ygc消耗的時間都很長。立刻就想到是否是由於不少鏈接還在keep alive狀態並無歸還給鏈接池,新的請求過來只能創建新的鏈接對象connection。且這些等待中的鏈接是不會被垃圾回收器回收的,由於還在alive。這樣就會出現已經建立的對象沒法回收,新鏈接對象卻在被不停建立的狀況。這樣就消耗盡了堆內存。markdown

3: 幾個好用的觀察heap的命令

能夠用這個命令看gc狀態。挺重要的,由於有些頻繁fgc的,就能夠提早處理了避免oom。less

能夠用這個命令直接看heap狀態。eclipse

jmap -heap pid
複製代碼

能夠用這個看堆上的對象【粗略看下 具體的還得用分析工具看鏈路】異步

jmap -histo:live pid | sort -k 2 -g -r| less
複製代碼

4: 論證

既然有了思路,就只是驗證就能夠了。看了事發地先後的日誌,基本上鎖定了事故現場。 首先在9點的時候有一個比較大的流量。2臺機器在1分鐘左右接了18.2w個請求。大部分請求都是這個:jvm

微信服務器在發送模版消息之後會推送【Template Send Job Finish】的事件到開發者服務器處理。其實挺坑的。若是超時了,微信還會每一個請求再發。

再加上爲了第一時間回覆給微信服務器success。處理回調的代碼邏輯用了異步邏輯。 可是咱們再次發了以前的錯誤,這個異步用了spring默認的@async註解。這個註解不初始化本身的線程池就是天坑。以前已經出了一次小事故 @Async用了springboot提供的線程池,竟然引起了事故?。這個會致使任務堆積。任務堆積致使鏈接超時。

總結下,就是天災【忽然大規模的請求】+ 人禍【代碼寫的有問題】。

5: 解決和回顧

  • 優化線程池配置 注入本身配置的線程池
  • 服務器擴容。不知不覺已經累計用戶快100w了,微信服務仍是隻有兩臺機器。此次加了兩臺。

過了7,8天,又經歷了幾回10w級別的回調,cpu基本上只有30util。效果很明顯。

相關文章
相關標籤/搜索