服務器CPU負載過高,如何定位問題


原文地址:https://www.jianshu.com/p/45c6bcb85934 

一、排查 CPU 故障的常用命令

  1. top:Linux 命令。可以實時查看各個進程的 CPU 使用情況。也可以查看最近一段時間的 CPU 使用情況。默認按 CPU 使用率排序。
  2. ps:Linux 命令。強大的進程狀態監控命令。可以查看進程以及進程中線程的當前 CPU 使用情況。屬於當前狀態的采樣數據。
  3. jstack:Java 提供的命令。可以查看某個進程的當前線程棧運行情況。根據這個命令的輸出可以定位某個進程的所有線程的當前運行狀態、運行代碼,以及是否死鎖等等。
  4. pstack:Linux 命令。可以查看某個進程的當前線程棧運行情況。

二、應用負載高的時候怎么辦?

一個應用占用 CPU 很高,除了確實是計算密集型應用之外,通常原因都是出現了死循環。CPU 負載過高解決問題過程:

  1. 使用【top】命令定位異常進程,可發現 PID 為 12836 的 CPU 和內存占用率都非常高:

     

備注: top 命令默認每 3 秒刷新一次。可以通過top -d <刷新時間間隔>來指定刷新頻率,如top -d 0.1top -d 0.01等。top 執行時,也可以按“s”鍵,修改時間間隔。

  1. 使用top -Hp PID查看該 PID 對應進程下各個線程的 CPU 使用情況:
     

     

     

PID(Process Identification)操作系統里指進程識別號,也就是進程標識符。操作系統里每打開一個程序都會創建一個進程 ID,即 PID。PID 是各進程的代號,每個進程有唯一的 PID 編號。它是進程運行時系統分配的,並不代表專門的進程。在運行時 PID 是不會改變標識符的,但是進程終止后 PID 標識符就會被系統回收,就可能會被繼續分配給新運行的程序。

  1. 使用【printf "%x\n" 線程號】將異常線程號轉化為 16 進制
 
  1. 使用【jstack 進程號|grep 16進制異常線程號 -A90】來定位異常代碼的位置(最后的-A90是日志行數,也可以輸出為文本文件或使用其他數字)。可以看到異常代碼的位置:

     

找到相應代碼檢查,發現確實有死循環存在。

三、什么場景會造成 CPU 低而負載確很高呢?

負載總結為一句話就是:需要運行處理但又必須等待隊列前的進程處理完成的進程個數。具體來說,也就是如下兩種情況:
等待被授權予 CPU 運行權限的進程、等待磁盤 I/O 完成的進程。

CPU 低而負載高也就是說等待磁盤 I/O 完成的進程過多,就會導致隊列長度過大,這樣就體現到負載過大了,但實際是此時 CPU 被分配去執行別的任務或空閑,具體場景有如下幾種:

①數據庫抖動,造成線程隊列 hang 住,負載升高
②磁盤讀寫請求過多就會導致大量 I/O 等待。CPU 的工作效率要高於磁盤,而進程在 CPU 上面運行需要訪問磁盤文件,這個時候 CPU 會向內核發起調用文件的請求,讓內核去磁盤取文件,這個時候會切換到其他進程或者空閑,這個任務就會轉換為不可中斷睡眠狀態。當這種讀寫請求過多就會導致不可中斷睡眠狀態的進程過多,從而導致負載高,CPU 低的情況。
③外接硬盤故障,常見有掛了 NFS,但是 NFS server 故障
比如系統掛載了外接硬盤如 NFS 共享存儲,經常會有大量的讀寫請求去訪問 NFS 存儲的文件,如果這個時候 NFS Server 故障,那么就會導致進程讀寫請求一直獲取不到資源,從而進程一直是不可中斷狀態,造成負載很高。

四、監控發現線上機器內存占用率居高不下,如何分析進行優化?

  1. 使用top -p pid針對所要查的 pid 查看該進程的 CPU 和內存以及負載情況。
  2. jmap -histo:live [pid],然后分析具體的對象數目和占用內存大小,從而定位代碼。
  3. jmap -dump:live,format=b,file=xxx.xxx [pid],然后利用 MAT 工具分析是否存在內存泄漏等等。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM