在實際的程序運行中,有很多問題只有在線上或者預發佈環境纔會出現,而線上又不能調試代碼,所以線上問題定位只能看日誌,系統狀態和dump線程。
一. 生產環境服務器變慢,診斷思路和性能評估
-
系統日誌:/var/log/messages
/var/log/messages 存放的是系統的日誌信息,它記錄了各種事件,基本上什麼應用都能往裏寫日誌,在做故障診斷時可以首先查看該文件內容。 -
JVM啓動參數配置
-Xms4g -Xmx4g:JVM堆的最小,最大值設置爲相等。
雖然最小堆大小設爲4g,但不是說項目一啓動立馬會申請4g內存,而是有個預熱過程(堆內存小於最小值)。可以設置啓動時直接向操作系統申請足夠的內存:-XX:+AlwaysPreTouch
另外,爲了規避程序中System.gc()帶來的Full GC風險,可以通過 -XX:+DisableExplicitGC禁止程序顯示調用GC方法
java -server jvm的各種參數 -jar 自己的jar/war包名
jps -l 查看java相關進程
-
整機: top 查看每個進程的情況,不要用ctrl+c退出top,按英文字母 q
load average: 系統的平均負載值,0.06 0.03 0.05 分別表示1min,10min,15min的負載
%Cpu(s): 多核,可以使用 lscpu查看cpu核數
99.8 id idle:空閒率,值越大越好
command: 表示啓動當前進程的命令
按數字鍵盤 1 查看每個cpu的性能數據
低配版top:uptime 系統性能命令的精簡版
-
cpu:vmstat
-
cpu: mpstat -P ALL 2 查看所有cpu核信息
-
cpu: pidstat
# 查看每個進程使用cpu的用量分解信息
pidstat -u 1 -p 進程編號
- 內存:free,pidstat
pidstat -p 進程號 -r 採樣間隔秒數
- 硬盤: df
- 磁盤IO: iostat,pidstat
查看額外: pidstat -d 採樣間隔秒數 -p 進程號
- 網絡IO:fstat
# 查看網絡連接數
netstat -nat | grep -i '8080' | wc -l
二. 假如生產環境出現CPU佔用過高,請談談你的分析思路和定位
-
整體思路
-
先用top命令找出cpu佔比最高的
-
ps -ef 進一步定位
-
定位到具體線程或者代碼
ps -mp 進程 -o THREAD,tid,name
-m 顯示所有的線程
-p pid 進程使用cpu的時間
-o 該參數後是用戶自定義格式
- 將十進制的線程ID轉換爲16進制英文小寫格式
printf "%x\n" 十進制線程ID
- jstack
# 將線程dump下來查看,然後用16進制的線程ID去dump裏找到對應的線程
jstack 進程ID > /home/log/dump
jstack 進程ID | grep tid(16進制線程ID小寫英文) -A60
top -H :查看每個線程的性能信息
這裏可以分3種情況:
(1) 某個線程cpu利用率一直100%,則說明這個線程有可能死循環,記住這個PID;
(2) 某個線程一直在TOP10的位置,說明這個線程可能有性能問題;
(3) cpu利用率高的幾個線程在不停變化,說明並不是某一個線程導致cpu偏高。
# 查找日誌
grep -rn ''關鍵字" a.log
三. 對於JDK自帶的JVM監控和性能分析工具用過哪些?一般你是怎麼用的?
-
性能監控工具
(1) jps: 虛擬機進程狀況工具
(2) jinfo: 配置信息工具
(3) jmap: 內存映像工具 ,生成Java應用程序的堆快照和對象的統計信息
映射堆快照: jmap -heap 進程ID
抓取堆內存: 生成 hprof 文件並下載到本地,MAT分析插件工具
(4) jstat: 統計信息監視工具,類加載統計,編譯統計,垃圾回收統計
jstat[-命令選項][VM進程ID] 間隔時間(單位毫秒) 查詢次數
(5) jstack: 堆棧異常跟蹤工具
在排查問題時,可以通過此命令 間隔性查看jvm線程情況(間隔時間 == 響應時間),多次結果比對,找出可能的線程,或者可以 自己編寫個 自動化 shell腳本,自動抓取 日誌。
(6) jcmd jcmd --help 查看幫助
(7) jconsole