1. 程式人生 > 程式設計 >java應用監測(4)-線上問題排查套路

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

。因此,總結CPU佔用過高問題可按下面套路:

# (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開發人員有幫助。

參考資料

相關閱讀