深入理解JVM(七)——效能監控工具

飄揚的紅領巾發表於2017-09-01

前言

  工欲善其事必先利其器,效能最佳化和故障排查在我們大都數人眼裡是件比較棘手的事情,一是需要具備一定的原理知識作為基礎,二是需要掌握排查問題和解決問題的流程、方法。本文就將介紹利用效能監控工具,幫助開發者更快更準的找到問題產生的根源。本文分為三部分,第一部分將介紹在Linux環境下的常用監控工具,第二部分介紹Windows環境下的監控工具,第三部分將透過一個案例,介紹利用這些監控工具一步一步找出java應用程式的問題。

Linux環境下的監控工具

  需要先宣告的是,下面介紹的部分工具其實在Liunx環境、Windows環境下都可以使用,只不過在不同的環境下使用什麼工具更合適。

  下面我們想象這麼一個場景:有一天運維人員看到生產環境下的伺服器負載升高、CPU飆升,記憶體佔用增大,請問接下來他該怎麼辦?可能有人會說,那就找到負載升高、CPU飆升。。的原因啊,如果是應用程式造成的就把它kill掉。如果採用這種方法,問題可能會短時間解決,但帶來的問題是應用在一段時間不可用,並且我們沒有找到問題發生的根源,下次重啟後,問題依然會產生。那麼如果出現類似的問題,嚴格的排查流程是怎樣的呢?在回答這個問題之前,我們先了解一下Linux上常用的幾個監控工具:

uptime

[root@centos7_template ~]# uptime 10:31:42 up 4 days, 1:01, 1 user,load average: 0.02, 0.02, 0.05
10:31:42    //當前系統時間
up 4 days, 1:01 //持續執行時間,時間越大,說明你的機器越穩定。 
1 user  //使用者連線數,是總連線數而不是使用者數 
load average: 0.02, 0.02, 0.05  //系統平均負載,統計最近1,5,15分鐘的系統平均負載

該命令將顯示目前伺服器持續執行的時間,以及負載情況。

透過這個命令,可以最簡便的看出系統當前基本狀態資訊,這裡面最有用是負載指標,如果你還想檢視當前系統的CPU/記憶體以及相關的程式狀態,可以使用TOP命令。

TOP

70NN3YT1%9[V1M5EU4{FPGQ

透過TOP命令可以詳細看出當前系統的CPU、記憶體、負載以及各程式狀態(PID、程式佔用CPU、記憶體、使用者)等。從上面的結果看出該系統上安裝了MySQL、java,可以看到他們各自的程式ID,假如這時Java程式佔用較高的CPU和記憶體,那麼你就要留心了,如果程式中沒有計算量特別大、佔用記憶體特別多的程式碼,可能你的java程式出現了未知的問題,可以根據程式ID做進一步的跟蹤。除了透過TOP命令找到程式資訊以外,還可以透過jdk自帶的工具JPS直接找到java程式的程式號。

JPS

image

可以看到jps命令直接羅列出了當前系統中存在的java程式,這裡第一個是jps命令自己的java程式,而另外一個是我啟動的nosql監控工具程式。透過這種方法查詢到java程式的程式ID後,可以進一步透過:

top -p 3618 // 這裡的3618就是上面查詢到的java程式的程式ID

image

透過此方法可以準確的檢視指定java程式的CPU/記憶體使用情況。

除此之外,vmstat命令也可以檢視系統CPU/記憶體、swap、io等情況:

VIBLT41${5HGEYJ}QZ)~T`T

上面的命令每隔1秒取樣一次,一共取樣四次。CPU佔用率很高,上下文切換頻繁,說明系統有執行緒正在頻繁切換,這可能是你的程式開啟了大量的執行緒存在資源競爭的情況。另外swap也是值得關注的指標,如果swpd過高則可能系統能使用的實體記憶體不足,不得不使用交換區記憶體,還有一個例外就是某些程式優先使用swap,導致swap飆升,而實體記憶體還有很多空餘,這些情況是需要注意的。

檢視系統指標,還有一個第三方工具:pidstat,這個工具還是很好用的,需要先安裝:

yum install sysstat

image

該命令監控程式id為3618的CPU狀態,每隔1秒取樣一次,一共取樣四次。“%CPU”表示CPU使用情況,“CPU”則表示正在使用哪個核的CPU,這裡為0表示正在使用第一個核。如果還要顯示執行緒ID,則可以使用:

pidstat -p 3618 -u -t 1 4

如果要監控磁碟讀寫情況,這可以使用:

image

pidstat還有其他的引數,可以透過pidstat --help獲取,再次不再贅述。

下面再介紹幾個JDK自帶有用的工具:jps、jstat、jmap、jstack

jps:上面我們已經使用過了,他可以羅列出目前再伺服器上執行的java程式及程式ID;

jstat:用於輸出java程式記憶體使用情況,包括新生代、老年代、後設資料區容量、垃圾回收情況。

image

上述命令輸出程式ID為3618的記憶體使用情況(每2000毫秒輸出一次,一共輸出20次)

  • S0:倖存1區當前使用比例
  • S1:倖存2區當前使用比例
  • E:伊甸園區使用比例
  • O:老年代使用比例
  • M:後設資料區使用比例
  • CCS:壓縮使用比例
  • YGC:年輕代垃圾回收次數
  • FGC:老年代垃圾回收次數
  • FGCT:老年代垃圾回收消耗時間
  • GCT:垃圾回收消耗總時間

jmap:用於輸出java程式中記憶體物件的情況,包括有哪些物件,物件的數量。

jmap -histo 3618

上述命令列印出程式ID為3618的記憶體情況。但我們常用的方式是將指定程式的記憶體heap輸出到外部檔案,再由專門的heap分析工具進行分析,例如mat(Memory Analysis Tool),所以我們常用的命令是:

jmap -dump:live,format=b,file=heap.hprof 3618

將heap.hprof傳輸出來到window電腦上使用mat工具分析:

{U[6FUIMFB%~8B~ZWC9C(RL

jstack:使用者輸出java程式執行緒棧的情況,常用於定位因為某些執行緒問題造成的故障或效能問題。

jstack 3618 > jstack.out

上述命令將程式ID為3618的棧資訊輸出到外部檔案,便於傳輸到windows電腦上進行分析。

Windows環境下的監控工具

Windows環境下的監控工具也有很多,但是本文主要推薦jvisualvm.exe、MemoryAnalyzer.exe,有了他們其他工具幾乎不需要了。

jvisualvm.exe在JDK安裝目錄下的bin目錄下面,雙擊即可開啟。

[(12G94WOFP`XLH1}BL[SD8

雙擊左側你需要監控的java程式即可對它進行監控,這個工具包括對CPU、記憶體、執行緒、類都做了監控,功能非常強大,上文中介紹的所有功能,其他在這個工具上都已經有了。當然怎麼用、如何分析它需要花時間去一點點積累。

MemoryAnalyzer.exe:上文我們已經提到,常用於分析記憶體堆使用情況,也是非常強大的工具。詳細使用方法,這裡就不再贅述,可以下載下來嘗試一下。

上述介紹了基於Linux、Windows環境的監控工具,有了這些工具我們就要利用他們做對應的事情,下面將透過一個簡單的案例,說明如何使用他們。

案例分析

首先透過上述的介紹,我們對故障排查流程應該有了一個印象,這裡先梳理出來:

image

案例:

 一個java應用啟動以後,使用人員發現應用不可用,針對該現象我們做以下分析排查:

1、首先檢視伺服器上的應用狀態。使用jps命令查詢當前在執行中的java程式:

image

這裡程式ID為6400的java應用就是我們剛啟用的,說明應用並沒有掛掉,還在執行中。

2、透過程式ID查詢所佔用的CPU、記憶體以及當前負載情況,top -p 6400。

 

 

image

從以上結果看出該應用並沒有引起系統負載過高,CPU、記憶體也沒有出現異常情況。

3、透過上述結果我們推測因為記憶體原因引起的故障可效能較小,所以我們優先排查執行緒棧,使用jstack命令,匯出執行緒棧。

jstack 6400 > stack.out

我們將該檔案傳輸出來便於檢視。

D{1SED$N[6E`YTTO9CZH%SQ

檢視執行緒棧可以看出,主執行緒處於執行狀態,而子執行緒ThreadA、ThreadB、ThreadC、ThreadD一邊在等待一個鎖,同時又持有另外一個鎖,其實看到這裡我們基本推斷該應用程式存在死鎖,因此造成執行緒等待,應用不可用。透過以上棧的資訊,我們就可以到程式程式碼中詳細檢視程式碼了,並且修改bug解決此問題。

死鎖原理補充:

image

如圖所示,造成死鎖的原因是執行緒之間存在相互制約的情況,而任一執行緒都無法繼續執行。

小結

  本文介紹了Linux、Windows環境下常用的監控工具,最後透過一個案例簡單說明故障排查的流程,怎麼使用監控工具找出應用故障的原因。

 

相關文章