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

什麼是cpu load 值

top命令中顯示的load average即爲最近1分鐘、5分鐘和15分鐘的系統平均負載。

CPU load過高產生的原因及排查
系統平均負載被定義爲在特定時間間隔內運行隊列中(在CPU上運行或者等待運行多少進程)的平均進程數。如果一個進程滿足以下條件則其就會位於運行隊列中:

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

在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纔是負載滿額。

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



【備註】本文是轉載過來用於學習的
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章