java應用監測(4)-線上問題排查套路
tags: java,troubleshooting,monitor
一句話概括:java應用線上問題如CPU過高,記憶體溢位,IO過高等問題如何排查,本文為你詳細講述。
1 引言
java應用上線執行後,免不了會有各種問題,總的來說問題會分為四大類:
- (1)CPU相關問題
- (2)記憶體相關問題
- (3)磁碟及IO相關問題
- (4)業務程式碼問題。
針對這些問題,線上如何進行監測與問題排查,是一個java開發人員的必要技能。下面將結合前面提到的java命令列工具,對這幾個問題的排查套路進行說明。
2 CPU問題排查套路
如果發現系統變慢變卡,應用響應變慢,首先要查的就是CPU使用情況,一般是程式佔用CPU過高,因此需要監測CPU的佔用情況,而java應用中與CPU相關的主要是執行緒的執行,因此具體到java應用,需要監測執行緒的執行狀態,對應就是命令列工具jstack
# (1) 查詢CPU佔用高的程式ID(PID)
top -c
# (2) 瞭解此程式的啟動引數
ps -ef|grep PID
或者
jinfo -flags PID
# (3) 列印執行緒堆疊資訊並輸出檔案
jstack -l PID > PID.dump
# (4) 根據程式查詢執行緒ID(TID)
top -H -p PID
# (5) 獲取TID的16進位制數
printf "%x\n" TID
# (6) 結合TID和執行緒堆疊資訊檔案查詢問題
- 可以使用文字工具直接檢視
- 可以使用 grep TID -A20 PID.dump 來檢視
- 需要配合執行緒狀態來檢查
複製程式碼
關於jstack
工具和執行緒狀態可檢視文章《java應用監測(3)-這些命令列工具你掌握了嗎》
3 記憶體問題排查套路
記憶體問題主要是java應用在執行過程中發生OOM(out of memory),因此需要建議在java應用啟動時,新增幾個引數,包括-Xloggc:file -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=logs/heapdump.hprof -XX:ErrorFile=logs/java_error_%p.log
。這樣當發生oom時,可以從dump出來的檔案來分析oom的原因。與記憶體問題相關的java命令列工具包括jmap
jstat
,因此記憶體OOM問題排查套路如下:
# (1)找到java應用程式(PID)
jps -lvm
或者
top -c
# (2)瞭解此程式啟動引數(特別是-Xms,-Xmx等)
ps -ef|grep PID
或者
jinfo -flags PID
# (3) 確認記憶體情況
jmap -heap PID
# (4) 查詢佔記憶體的大物件
jmap -histo:live PID
# (5) dump出堆檔案,以便使用工具分析
jmap -dump:file=./heap.hprof PID
# (6) 檢視GC變化情況,如下每秒列印一次
jstat -gc PID 1000
# (7) 結合日誌檔案出錯資訊及dump出來的堆檔案分析OOM和GC情況
- 記憶體分配小,適當調整記憶體
- 物件被頻繁建立,且不釋放,優化程式碼
- young gc頻率太高,檢視-Xmn、-XX:SurvivorRatio等引數設定是否合理
複製程式碼
關於OOM,官方檔案有關於OOM的說明(https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/memleaks002.html
),
主要分為以下幾大類:
-
java.lang.OutOfMemoryError: Java heap space
,堆的記憶體佔用已經達到-Xmx
設定的最大值,無法建立新物件,簡單的可以考慮通過調整-Xmx
引數來解決。 -
java.lang.OutOfMemoryError: GC Overhead limit exceeded
,表示GC一直在執行且java程式執行很慢,通常會丟擲此異常,java堆的分配的空間很小以至於新資料無法放到堆中。考慮調整堆大小,如果想關閉此輸出,可用引數來關閉-XX:-UseGCOverheadLimit
。 -
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
,java應用嘗試分配大於堆大小的陣列,如堆大小是256M,卻要分配512M的陣列,則會報錯。考慮調整堆大小或者修改程式碼 -
java.lang.OutOfMemoryError: Metaspace
,當類元資料所需的本機記憶體量超過時MaxMetaSpaceSize時報出,考慮調整MaxMetaSpaceSize。 -
java.lang.OutOfMemoryError: request size bytes for reason. Out of swap space?
當來自本機堆的分配失敗並且本機堆可能接近耗盡時會報此錯誤,需要檢視日誌來處理。 -
java.lang.OutOfMemoryError: Compressed class space
,JVM的非堆結構中,類指標存放空間不足,考慮使用CompressedClassSpaceSize
來調整。 -
java.lang.OutOfMemoryError: reason stack_trace_with_native_method
,JVM的本地方法區不足,在Java本機介面(JNI)或本機方法中檢測到分配失敗,需要查詢對應堆疊資訊來查詢。
4 磁碟及IO問題排查套路
java應用執行過程中,會涉及日誌產生,對磁碟的讀寫等操作,也有可能有各種問題,如磁碟不足(日誌輸出過多)、、磁碟讀寫IO比較慢、IO過於頻繁等。一般來說,可以按以下套路進行排查:
# (1) 檢視磁碟容量情況
df -h
# (2) 檢視檔案大小和目錄大小
ls -l 或者直接ll
du -h --max-depth=1
# (3) 檢視IO情況,找到IO讀寫頻繁的程式PID
iotop -d 1 # 1秒列印一次
或者
iostat -d -x -k 1 #1秒列印一次
# (4) 使用stack列印執行緒堆疊資訊,排查IO相關程式碼
# (5) 有時候若想測試磁碟的讀寫速度(特別是虛擬機器器),可以使用dd
# 示例:測資料卷掛載目錄的純寫速度
dd if=/dev/zero of=/資料卷目錄/test.iso bs=8k count=1000000
複製程式碼
5 業務問題排查套路
業務問題,主要是涉及到程式碼邏輯層面的,主要是查詢日誌輸出,方法是否按正確的邏輯執行,因此一般的排查套路如下:
# (1) 實時日誌輸出查詢
tail -fn 100 log_file
# (2) 根據日誌輸出的關鍵字來定位問題
grep keyWord log_file # 關鍵字所在行
grep -C n keyWord log_file # 關鍵字所在前後n行
# (3) 日誌檔案使用視覺化文字工具分析(notepad++,sublime,大檔案檢視如EmEditor)
# (4) 使用線上工具直接檢測方法的引數、返回值,異常情況等等,如Btrace,arthas等。
複製程式碼
關於java線上問題的診斷工具包括Btrace及arthas,本系列後續會有相應的文章進行介紹。
6 總結
本文對java應用線上遇到的問題分為四大類,分別是(1)CPU相關問題,(2)記憶體相關問題,(3)磁碟及IO相關問題,(4)業務程式碼問題。針對各種問題,按照一定的套路,結合java的命令列工具和線上診斷工具,可以很方便地給java應用進行排查。希望本文給相應的java開發人員有幫助。
參考資料
-
Understand the OutOfMemoryError Exception:
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/memleaks002.html
-
這部技術葵花寶典真的很硬核:
https://mp.weixin.qq.com/s/NJPXFMgbwXWkzVLDK12Gfg
-
目前最全的Java服務問題排查套路:
https://mp.weixin.qq.com/s/SuFPeWxtjHdXAcu6hkmBlA
-
JDK工具參考檔案:
https://docs.oracle.com/javase/8/docs/technotes/tools/unix
-
示例程式碼地址:
https://github.com/mianshenglee/my-example/tree/master/java-monitor-example
相關閱讀
-
java應用監測(1)-java程式設計師應該知道的應用監測技術:
https://juejin.im/post/5d5fde94f265da03d42fae8b
-
java應用監測(2)-java命令的祕密:
https://juejin.im/post/5d60c8286fb9a06ada54bb87
-
java應用監測(3)-這些命令列工具你掌握了嗎:
https://juejin.im/post/5d6207c6f265da03b46bf933