1. 程式人生 > >CPU load過高產生的原因及排查

CPU load過高產生的原因及排查

之前面試被問到,造成CPU load過高的原因有哪些?如何快速排查其原因?
開一貼,總結該相關知識

什麼是cpu load 值

top命令中顯示的load average即為最近1分鐘、5分鐘和15分鐘的系統平均負載。
這裡寫圖片描述

系統平均負載被定義為在特定時間間隔內執行佇列中(在CPU上執行或者等待執行多少程序)的平均程序數。如果一個程序滿足以下條件則其就會位於執行佇列中:

  • 它沒有在等待I/O操作的結果
  • 它沒有主動進入等待狀態(也就是沒有呼叫’wait’)
  • 沒有被停止(例如:等待終止)

在Linux中,程序分為三種狀態,一種是阻塞的程序blocked process(等待I/O裝置的資料或者系統調),一種是可執行的程序runnable process,另外就是正在執行的程序running process。

程序可執行狀態時,它處在一個執行佇列run queue中,與其他可執行程序爭奪CPU時間。 系統的load是指正在執行和準備好執行的程序的總數。比如現在系統有2個正在執行的程序,3個可執行程序,那麼系統的load就是5。load average就是一定時間內的load數量。

什麼因素構成了cpu load的大小

衡量CPU 系統負載的指標是load,load 就是對計算機系統能夠承擔的多少負載的度量,簡單的說是程序佇列的長度。請求大於當前的處理能力,會出現等待,引起load升高。
對於本文剛剛開頭顯示的 load average 0.21 0.10 0.03

很多人會這樣理解負載均值:三個數分別代表不同時間段的系統平均負載(一分鐘、五 分鐘、以及十五分鐘),它們的數字當然是越小越好。數字越高,說明伺服器的負載越大,這也可能是伺服器出現某種問題的訊號。而事實不完全如此,是什麼因素構成了負載均值的大小,以及如何區分它們目前的狀況是 “好”還是“糟糕”?什麼時候應該注意哪些不正常的數值?

回答這些問題之前,首先需要了解下這些數值背後的些知識。我們先用最簡單的例子說明, 一臺只配備一塊單核處理器的伺服器。

行車過橋

  一隻單核的處理器可以形象得比喻成一條單車道。設想下,你現在需要收取這條道路的過橋費 — 忙於處理那些將要過橋的車輛。你首先當然需要了解些資訊,例如車輛的載重、以及 還有多少車輛正在等待過橋。如果前面沒有車輛在等待,那麼你可以告訴後面的司機通過。 如果車輛眾多,那麼需要告知他們可能需要稍等一會。

  因此,需要些特定的代號表示目前的車流情況,例如:

  0.00 表示目前橋面上沒有任何的車流。 實際上這種情況與 0.00 和 1.00 之間是相同的,總而言之很通暢,過往的車輛可以絲毫不用等待的通過。

  1.00 表示剛好是在這座橋的承受範圍內。 這種情況不算糟糕,只是車流會有些堵,不過這種情況可能會造成交通越來越慢。
  
  超過 1.00,那麼說明這座橋已經超出負荷,交通嚴重的擁堵。 那麼情況有多糟糕? 例如 2.00 的情況說明車流已經超出了橋所能承受的一倍,那麼將有多餘過橋一倍的車輛正在焦急的等待。3.00 的話情況就更不妙了,說明這座橋基本上已經快承受不了,還有超出橋負載兩倍多的車輛正在等待。
  上面的情況和處理器的負載情況非常相似。一輛汽車的過橋時間就好比是處理器處理某執行緒 的實際時間。Unix 系統定義的程序執行時長為所有處理器核心的處理時間加上執行緒在佇列中等待的時間。

  和收過橋費的管理員一樣,你當然希望你的汽車(操作)不會被焦急的等待。所以,理想狀態 下,都希望負載平均值小於 1.00 。當然不排除部分峰值會超過 1.00,但長此以往保持這 個狀態,就說明會有問題,這時候你應該會很焦急。
“所以你說的理想負荷為 1.00 ?”嗯,這種情況其實並不完全正確。負荷 1.00 說明系統已經沒有剩餘的資源了。在實際情況中 ,有經驗的系統管理員都會將這條線劃在 0.70。如果長期你的系統負載在 0.70 上下,那麼你需要在事情變得更糟糕之前,花些時間瞭解其原因。

多核處理器: 系統還是以處理器的核心數量計算負載均值
在多核處理中,你的系統均值不應該高於處理器核心的總數量。繼續針對上述的汽車過橋問題,如果是雙核CPU,那麼負載在2.0才是負載滿額。如下是對於雙核處理器的輸出

uptime
17:57  up 22 days,  8:29, 3 users, load averages: 2.04 2.04 2.01

cpu load 過高原因以及排查

造成cpu load過高的原因.從程式語言層次上full gc次數的增大或死迴圈都有可能造成cpu load 增高

具體的排查一句話描述就是

首先要找到哪幾個執行緒在佔用cpu,之後再通過執行緒的id值在堆疊檔案中查詢具體的執行緒,看看出來什麼問題。

尋找最佔CPU的程序

  • 通過命令 ps ux
  • 通過top -c命令顯示程序執行資訊列表 (按鍵P按CPU佔有資源排序)

尋找最耗CPU的執行緒

  • top -Hp 程序ID 顯示一個程序ID的執行緒執行資訊列表 (按鍵P按CPU佔有資源排序)
    如果該程序是java程序,需要具體檢視是哪段程式碼造成的CPU負載過高,根據上述獲得到的執行緒ID可以使用JDK下的jstack來檢視堆疊。

由於在堆疊中執行緒id是用16進製表示的,因此可以將上述執行緒轉化成16進位制的表示。

jstack java程序id  | grep 16進位制的執行緒id  -C5 --color