JVM 線上故障排查基本操作
# 前言
對於後端程式設計師,特別是 Java 程式設計師來講,排查線上問題是不可避免的。各種 CPU 飈高,記憶體溢位,頻繁 GC 等等,這些都是令人頭疼的問題。樓主同樣也遇到過這些問題,那麼,遇到這些問題該如何解決呢?
首先,出現問題,肯定要先定位問題所在,然後分析問題原因,再然後解決問題,最後進行總結,防止下次再次出現。
今天的文章,就如我們的題目一樣,講的是基本操作,也就是一些排查線上問題的基本方法。為什麼這麼說呢?因為線上問題千奇百怪,就算是身經百戰的專家也會遇到棘手的問題,因此不可能在一篇文章裡說完,還有一個最重要的原因,當然就是樓主的水平不到位。
但不到位歸不到位,任何經驗都是值得記錄的,因此,樓主有必要將這些問題記錄一下。
還有,本文的排查環境是 Linux.
#1. CPU 飈高
線上 CPU 飈高問題大家應該都遇到過,那麼如何定位問題呢?
思路:首先找到 CPU 飈高的那個 Java 程式,因為你的伺服器會有多個 JVM 程式。然後找到那個程式中的 “問題執行緒”,最後根據執行緒堆疊資訊找到問題程式碼。最後對程式碼進行排查。
如何操作呢?
- 通過 top 命令找到 CPU 消耗最高的程式,並記住程式 ID。
- 再次通過 top -Hp [程式 ID] 找到 CPU 消耗最高的執行緒 ID,並記住執行緒 ID.
- 通過 JDK 提供的 jstack 工具 dump 執行緒堆疊資訊到指定檔案中。具體命令:jstack -l [程式 ID] >jstack.log。
- 由於剛剛的執行緒 ID 是十進位制的,而堆疊資訊中的執行緒 ID 是16進位制的,因此我們需要將10進位制的轉換成16進位制的,並用這個執行緒 ID 在堆疊中查詢。使用 printf "%x\n" [十進位制數字] ,可以將10進位制轉換成16進位制。
- 通過剛剛轉換的16進位制數字從堆疊資訊裡找到對應的執行緒堆疊。就可以從該堆疊中看出端倪。
從樓主的經驗來看,一般是某個業務死迴圈沒有出口,這種情況可以根據業務進行修復。還有 C2 編譯器執行編譯時也會搶佔 CPU,什麼是 C2編譯器呢?當 Java 某一段程式碼執行次數超過10000次(預設)後,就會將該段程式碼從解釋執行改為編譯執行,也就是編譯成機器碼以提高速度。而這個 C2編譯器就是做這個的。如何解決呢?專案上線後,可以先通過壓測工具進行預熱,這樣,等使用者真正訪問的時候,C2編譯器就不會干擾應用程式了。如果是 GC 執行緒導致的,那麼極有可能是 Full GC ,那麼就要進行 GC 的優化。
2. 記憶體問題排查
說完了 CPU 的問題排查,再說說記憶體的排查,通常,記憶體的問題就是 GC 的問題,因為 Java 的記憶體由 GC 管理。有2種情況,一種是記憶體溢位了,一種是記憶體沒有溢位,但 GC 不健康。
記憶體溢位的情況可以通過加上 -XX:+HeapDumpOnOutOfMemoryError 引數,該引數作用是:在程式記憶體溢位時輸出 dump 檔案。
有了 dump 檔案,就可以通過 dump 分析工具進行分析了,比如常用的MAT,Jprofile,jvisualvm 等工具都可以分析,這些工具都能夠看出到底是哪裡溢位,哪裡建立了大量的物件等等資訊。
第二種情況就比較複雜了。GC 的健康問題。
通常一個健康的 GC 是什麼狀態呢?根據樓主的經驗,YGC 5秒一次左右,每次不超過50毫秒,FGC 最好沒有,CMS GC 一天一次左右。
而 GC 的優化有2個維度,一是頻率,二是時長。
我們看YGC,首先看頻率,如果 YGC 超過5秒一次,甚至更長,說明系統記憶體過大,應該縮小容量,如果頻率很高,說明 Eden 區過小,可以將 Eden 區增大,但整個新生代的容量應該在堆的 30% - 40%之間,eden,from 和 to 的比例應該在 8:1:1左右,這個比例可根據物件晉升的大小進行調整。
如果 YGC 時間過長呢?YGC 有2個過程,一個是掃描,一個是複製,通常掃描速度很快,複製速度相比而言要慢一些,如果每次都有大量物件要複製,就會將 STW 時間延長,還有一個情況就是 StringTable ,這個資料結構中儲存著 String.intern 方法返回的常連池的引用,YGC 每次都會掃描這個資料結構(HashTable),如果這個資料結構很大,且沒有經過 FGC,那麼也會拉長 STW 時長,還有一種情況就是作業系統的虛擬記憶體,當 GC 時正巧作業系統正在交換記憶體,也會拉長 STW 時長。
再來看看FGC,實際上,FGC 我們只能優化頻率,無法優化時長,因為這個時長無法控制。如何優化頻率呢?
首先,FGC 的原因有幾個,1 是 Old 區記憶體不夠,2 是後設資料區記憶體不夠,3 是 System.gc(), 4 是 jmap 或者 jcmd,5 是CMS Promotion failed 或者 concurrent mode failure,6 JVM 基於悲觀策略認為這次 YGC 後 Old 區無法容納晉升的物件,因此取消 YGC,提前 FGC。
通常優化的點是 Old 區記憶體不夠導致 FGC。如果 FGC 後還有大量物件,說明 Old 區過小,應該擴大 Old 區,如果 FGC 後效果很好,說明 Old 區存在了大量短命的物件,優化的點應該是讓這些物件在新生代就被 YGC 掉,通常的做法是增大新生代,如果有大而短命的物件,通過引數設定物件的大小,不要讓這些物件進入 Old 區,還需要檢查晉升年齡是否過小。如果 YGC 後,有大量物件因為無法進入 Survivor 區從而提前晉升,這時應該增大 Survivor 區,但不宜太大。
上面說的都是優化的思路,我們也需要一些工具知道 GC 的狀況。
JDK 提供了很多的工具,比如 jmap ,jcmd 等,oracle 官方推薦使用 jcmd 代替 jmap,因為 jcmd 確實能代替 jmap 很多功能。jmap 可以列印物件的分佈資訊,可以 dump 檔案,注意,jmap 和 jcmd dump 檔案的時候會觸發 FGC ,使用的時候注意場景。
還有一個比較常用的工具是 jstat,該工具可以檢視GC 的詳細資訊,比如eden ,from,to,old 等區域的記憶體使用情況。
還有一個工具是 jinfo,該工具可以檢視當前 jvm 使用了哪些引數,並且也可以在不停機的情況下修改引數。
包括我們上面說的一些分析 dump 檔案的視覺化工具,MAT,Jprofile,jvisualvm 等,這些工具可以分析 jmap dump 下來的檔案,看看哪個物件使用的記憶體較多,通常是能夠查出問題的。
還有很重要的一點就是,線上環境一定要帶上 GC 日誌!!!
總結
基於文章的標題,我們這個是基本操作,故障排查是說不完的話題,每個故障涉及的知識也都很多,因此,我們在學習了基本的排查之後,還需要學習更多事故排查技術,比如排查 IO,網路,TCP 連線等等。樓主將在後面的文章中將這些基本操作都記錄下來。
good luck!!!!
相關文章
- JVM線上CPU 飈高故障排查基本操作JVM
- 線上故障的排查清單,運維拿走不謝!運維
- dpdk-lvs的一次線上故障排查報告
- 線上故障突突突?如何緊急診斷、排查與恢復
- rsync 故障排查整理
- 應用故障排查
- SANGFOR NGAF雙機主備專線故障的排查
- JVM 常見線上問題 → CPU 100%、記憶體洩露 問題排查JVM記憶體洩露
- 線上FullGC問題排查實踐——手把手教你排查線上問題GC
- 光纖故障診斷和故障排查
- 如何應對線上故障?
- MinIO線上故障演練
- MogDB openGauss故障排查流程
- 一次線上JVM記憶體異常排查 -- 物件之間的複製JVM記憶體物件
- 記一次隱藏很深的 JVM 線上慘案的分析、排查、解決!JVM
- JVM系列(七) – JVM線上監控工具JVM
- JVM系列(七) - JVM線上監控工具JVM
- 線性表的基本操作
- Linux排查JVM問題LinuxJVM
- 線上故障處理手冊
- JVM問題排查步驟JVM
- rabbitmq 原理、叢集、基本運維操作、常見故障處理MQ運維
- 004.OpenShift命令及故障排查
- 記一次線上 K8s Ingress 訪問故障排查,最後竟不是 Post 的鍋K8S
- 線上問題排查神器入門——Arthas
- linux出現故障字符集亂碼故障排查思路Linux
- 記IPSec VPN對接故障的排查
- 伺服器網路故障如何排查伺服器
- 線上服務Java程序假死快速排查、分析Java
- 一次線上死迴圈的排查
- 線上的一次fullgc排查過程GC
- 記一次線上FGC問題排查GC
- Oracle dos連線資料庫基本操作Oracle資料庫
- 後端人員如何應對線上故障後端
- 使用jvm工具排查系統問題JVM
- Java線上問題排查神器Arthas實戰分析Java
- 線上併發事務死鎖問題排查
- 故障排查工具-strace,tcpdump的簡單使用TCP
- 伺服器的路由故障怎麼排查伺服器路由