前言
對于互聯(lián)網公司,線上CPU飆升的問題很常見(例如某個活動開始,流量突然飆升時),按照本文的步驟排查,基本1分鐘即可搞定!特此整理排查方法一篇,供大家參考討論提高。
線上系統(tǒng)突然運行緩慢,CPU飆升,甚至到100%,以及Full GC次數過多,接著就是各種報警:例如接口超時報警等。此時急需快速線上排查問題。
不管什么問題,既然是CPU飆升,肯定是查一下耗CPU的線程,然后看看GC。
一、常見能夠引起CPU100%異常的情況都有哪些?
-
Java 內存不夠或者溢出導致GC overhead limit exceeded。
-
代碼中互相競爭導致的死鎖。
-
特別耗費計算資源的操作,比如正則匹配,Java中的正則匹配默認有回溯問題,復雜的正則匹配引起的CPU異常。
-
死循環(huán)引起的CPU高度密集計算。
針對第1種,根據Oracle官方資料,GC overhead limit exceeded表示JVM一直在GC導致應用程序變慢,具體量化指標就是JVM執(zhí)行垃圾回收花費超過98%的時間,但釋放出的可用堆內存卻少于2%,連續(xù)多次(一般5次)GC回收的內存都不足2%的情況下就會拋出此異常。
經過垃圾回收每次釋放的內存都少于2%很容易又被新生對象填滿,JVM快速進入下一次垃圾回收,無限循環(huán),由此引起頻繁的GC長期消耗我們服務器CPU資源,從而使CPU使用率達到100%
我們可以使用-XX:-UseGCOverheadLimit這個參數關閉GC overhead limit exceeded,但這樣治標不治本,建議檢查應用程序的內存使用是否合理以及是否需要增加堆內存。
二、服務器CPU使用率飆升異常,黃金4步排查法
-
TOP命令找到占用CPU高的Java進程PID
top
-
根據進程ID找到占用CPU高的線程
ps -mp pid -o THREAD,tid | sort -r
-
將指定的線程ID輸出為16進制格式
printf “%x\n” tid
-
根據16進制格式的線程ID查找線程堆棧信息
jstack pid |grep tid -A 50
獲取到線程堆棧信息就好辦了,以上即是采用單線程模擬一個復雜的正則匹配的堆棧示例圖,可以看得出線程都在指向regex.Pattern,在生產多線程環(huán)境下這個復雜正則匹配會導致CPU利用率奇高。
三、排查 CPU 故障的常用命令
- top:Linux 命令。可以實時查看各個進程的 CPU 使用情況。也可以查看最近一段時間的 CPU 使用情況。默認按 CPU 使用率排序。
- ps:Linux 命令。強大的進程狀態(tài)監(jiān)控命令??梢圆榭催M程以及進程中線程的當前 CPU 使用情況。屬于當前狀態(tài)的采樣數據。
- jstack:Java 提供的命令??梢圆榭茨硞€進程的當前線程棧運行情況。根據這個命令的輸出可以定位某個進程的所有線程的當前運行狀態(tài)、運行代碼,以及是否死鎖等等。
- pstack:Linux 命令??梢圆榭茨硞€進程的當前線程棧運行情況。
四、什么場景會造成 CPU 低而負載確很高呢?
負載總結為一句話就是:需要運行處理但又必須等待隊列前的進程處理完成的進程個數。具體來說,也就是如下兩種情況:
等待被授權予 CPU 運行權限的進程、等待磁盤 I/O 完成的進程。文章來源:http://www.zghlxwxcb.cn/news/detail-677686.html
CPU 低而負載高也就是說等待磁盤 I/O 完成的進程過多,就會導致隊列長度過大,這樣就體現到負載過大了,但實際是此時 CPU 被分配去執(zhí)行別的任務或空閑,具體場景有如下幾種:文章來源地址http://www.zghlxwxcb.cn/news/detail-677686.html
- 數據庫抖動,造成線程隊列 hang 住,負載升高
- 磁盤讀寫請求過多就會導致大量 I/O 等待。CPU 的工作效率要高于磁盤,而進程在 CPU 上面運行需要訪問磁盤文件,這個時候 CPU 會向內核發(fā)起調用文件的請求,讓內核去磁盤取文件,這個時候會切換到其他進程或者空閑,這個任務就會轉換為不可中斷睡眠狀態(tài)。當這種讀寫請求過多就會導致不可中斷睡眠狀態(tài)的進程過多,從而導致負載高,CPU 低的情況。
- 外接硬盤故障,常見有掛了 NFS,但是 NFS server 故障比如系統(tǒng)掛載了外接硬盤如 NFS 共享存儲,經常會有大量的讀寫請求去訪問 NFS 存儲的文件,如果這個時候 NFS Server 故障,那么就會導致進程讀寫請求一直獲取不到資源,從而進程一直是不可中斷狀態(tài),造成負載很高。
五、監(jiān)控發(fā)現線上機器內存占用率居高不下,如何分析進行優(yōu)化?
- 使用
top -p pid
針對所要查的 pid 查看該進程的 CPU 和內存以及負載情況。 -
jmap -histo:live [pid]
,然后分析具體的對象數目和占用內存大小,從而定位代碼。 -
jmap -dump:live,format=b,file=xxx.xxx [pid]
,然后利用 MAT 工具分析是否存在內存泄漏等等。
到了這里,關于【Java】 服務器cpu過高如何排查和解決?的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!