天天看點

淺談 Linux 高負載的系統化分析

講解 Linux Load 高如何排查的話題屬于老生常談了,但多數文章隻是聚焦了幾個點,缺少整體排查思路的介紹。所謂 “授人以魚不如授人以漁”。本文試圖建立一個方法和套路,來幫助讀者對 Load 高問題排查有一個更全面的認識。

從消除誤解開始

沒有基線的 Load,是不靠譜的 Load

從接觸 Unix/Linux 系統管理的第一天起,很多人就開始接觸

System Load Average

這個監控名額了,然而,并非所有人都知道這個名額的真正含義。一般說來,經常能聽到以下誤解:

  • Load 高是 CPU 負載高……

    傳統 Unix 于 Linux 設計不同。Unix 系統,Load 高就是可運作程序多引發的,但對 Linux 來說不是。對 Linux 來說 Load 高可能有兩種情況:

    • 系統中處于

      R

      狀态的程序數增加引發的
    • D

  • Loadavg 數值大于某個值就一定有問題……

    Loadavg 的數值是相對值,受到 CPU 和 IO 裝置多少的影響,甚至會受到某些軟體定義的虛拟資源的影響。Load 高的判斷需要基于某個曆史基線 (Baseline),不能無原則的跨系統去比較 Load。

  • Load 高系統一定很忙…..

    Load 高系統可以很忙,例如 CPU 負載高,CPU 很忙。但 Load 高,系統不都很忙,如 IO 負載高,磁盤可以很忙,但 CPU 可以比較空閑,如 iowait 高。這裡要注意,iowait 本質上是一種特殊的 CPU 空閑狀态。另一種 Load 高,可能 CPU 和磁盤外設都很空閑,可能支援鎖競争引起的,這時候 CPU 時間裡,iowait 不高,但 idle 高。

Brendan Gregg 在最近的部落格 [Linux Load Averages: Solving the Mystery] (http://www.brendangregg.com/blog/2017-08-08/linux-load-averages.html) 中,讨論了 Unix 和 Linux Load Average 的差異,并且回朔到 24 年前 Linux 社群的讨論,并找到了當時為什麼 Linux 要修改 Unix Load Average 的定義。文章認為,正是由于 Linux 引入的

D

狀态線程的計算方式,進而導緻 Load 高的原因變得含混起來。因為系統中引發

D

狀态切換的原因實在是太多了,絕非 IO 負載,鎖競争這麼簡單!正是由于這種含混,Load 的數值更加難以跨系統,跨應用類型去比較。所有 Load 高低的依據,全都應該基于曆史的基線。本微信公衆号也曾寫過一篇相關文章,可以參見

Linux Load Average那些事兒

淺談 Linux 高負載的系統化分析

如何排查 Load 高的問題

如前所述,由于在 Linux 作業系統裡,Load 是一個定義及其含混的名額,排查 loadavg 高就是一個很複雜的過程。其基本思路就是,根據引起 Load 變化的根源是

R

狀态任務增多,還是

D

狀态任務增多,來進入到不同的流程。

這裡給出了 Load 增高的排查的一般套路,僅供參考:

淺談 Linux 高負載的系統化分析

在 Linux 系統裡,讀取

/proc/stat

檔案,即可擷取系統中

R

狀态的程序數;但

D

狀态的任務數恐怕最直接的方式還是使用

ps

指令比較友善。而

/proc/stat

檔案裡

procs_blocked

則給出的是處于等待磁盤 IO 的程序數:

淺談 Linux 高負載的系統化分析

通過簡單區分 

R

 狀态任務增多,還是 

D

 狀态任務增多,我們就可以進入到不同的排查流程裡。下面,我們就這個大圖的排查思路,做一個簡單的梳理。

R

狀态任務增多

即通常所說的 CPU 負載高。此類問題的排查定位主要思路是系統,容器,程序的運作時間分析上,找到在 CPU 上的熱點路徑,或者分析 CPU 的運作時間主要是在哪段代碼上。

CPU

user

sys

時間的分布通常能幫助人們快速定位與使用者态程序有關,還是與核心有關。另外,CPU 的 run queue 長度和排程等待時間,非主動的上下文切換 (nonvoluntary context switch) 次數都能幫助大緻了解問題的場景。

是以,如果要将問題的場景關聯到相關的代碼,通常需要使用

perf

systemtap

,

ftrace

這種動态的跟蹤工具。

關聯到代碼路徑後,接下來的代碼時間分析過程中,代碼中的一些無效的運作時間也是分析中首要關注的,例如使用者态和核心态中的自旋鎖 (Spin Lock)。

當然,如果 CPU 上運作的都是有非常意義,非常有效率的代碼,那唯一要考慮的就是,是不是負載真得太大了。

D

根據 Linux 核心的設計,

D

狀态任務本質上是

TASK_UNINTERRUPTIBLE

引發的主動睡眠,是以其可能性非常多。但是由于 Linux 核心 CPU 空閑時間上對 IO 棧引發的睡眠做了特殊的定義,即

iowait

,是以

iowait

成為

D

狀态分類裡定位是否 Load 高是由 IO 引發的一個重要參考。

當然,如前所述,

/proc/stat

中的

procs_blocked

的變化趨勢也可以是一個非常好的判定因

iowait

引發的 Load 高的一個參考。

iowait

很多人通常都對 CPU

iowait

有一個誤解,以為

iowait

高是因為這時的 CPU 正在忙于做 IO 操作。其實恰恰相反,

iowait

高的時候,CPU 正處于空閑狀态,沒有任何任務可以運作。隻是因為此時存在已經發出的磁盤 IO,是以這時的空閑狀态被辨別成了

iowait

,而不是

idle

但此時,如果用

perf probe

指令,我們可以清楚得看到,在

iowait

狀态的 CPU,實際上是運作在 pid 為 0 的 idle 線程上:

淺談 Linux 高負載的系統化分析

相關的 idle 線程的循環如何分别對 CPU 

iowait

 和 

idle

 計數的代碼,如下所示:

淺談 Linux 高負載的系統化分析

而 Linux IO 棧和檔案系統的代碼則會調用

io_schedule

,等待磁盤 IO 的完成。這時候,對 CPU 時間被記為

iowait

起關鍵計數的原子變量

rq->nr_iowait

則會在睡眠前被增加。注意,io_schedule 在被調用前,通常 caller 會先将任務顯式地設定成

TASK_UNINTERRUPTIBLE

狀态:

淺談 Linux 高負載的系統化分析

CPU 

idle

 高

如前所述,有相當多的核心的阻塞,即

TASK_UNINTERRUPTIBLE

的睡眠,實際上與等待磁盤 IO 無關,如核心中的鎖競争,再如記憶體直接頁回收的睡眠,又如核心中一些代碼路徑上的主動阻塞,等待資源。

Brendan Gregg 在最近的部落格 [Linux Load Averages: Solving the Mystery] (http://www.brendangregg.com/blog/2017-08-08/linux-load-averages.html)中,使用

perf

指令産生的

TASK_UNINTERRUPTIBLE

的睡眠的火焰圖,很好的展示了引起 CPU

idle

高的多樣性。本文不在贅述。

是以,CPU

idle

高的分析,實質上就是分析核心的代碼路徑引起阻塞的主因是什麼。通常,我們可以使用

perf inject

perf record

記錄的上下文切換的事件進行處理,關聯出程序從 CPU 切出 (swtich out) 和再次切入 (switch in) 的核心代碼路徑,生成一個所謂的 Off CPU 火焰圖.

當然,類似于鎖競争這樣的比較簡單的問題,Off CPU 火焰圖足以一步定位出問題。但是對于更加複雜的因

D

狀态而阻塞的延遲問題,可能 Off CPU 火焰圖隻能給我們一個調查的起點。

例如,當我們看到,Off CPU 火焰圖的主要睡眠時間是因為

epoll_wait

等待引發的。那麼,我們繼續要排查的應該是網絡棧的延遲,即本文大圖中的 Net Delay 這部分。

至此,你也許會發現,CPU

iowait

idle

高的性能分析的實質就是

延遲分析

。這就是大圖按照核心中資源管理的大方向,将延遲分析細化成了六大延遲分析:

  • CPU 延遲
  • 記憶體延遲
  • 檔案系統延遲
  • IO 棧延遲
  • 網絡棧延遲
  • 鎖及同步原語競争

任何上述代碼路徑引發的

TASK_UNINTERRUPTIBLE

的睡眠,都是我們要分析的對象!

以問題結束

限于篇幅,本文很難将其所涉及的細節一一展開,因為讀到這裡,你也許會發現,原來 Load 高的分析,實際上就是對系統的全面負載分析。怪不得叫 System Load 呢。這也是 Load 分析為什麼很難在一篇文章裡去全面覆寫。

本文也開啟了淺談 Linux 性能分析系列的第一章。後續我們會推出系列文章,就前文所述的六大延遲分析,一一展開介紹,敬請期待……

關于作者

楊勇 (Oliver Yang),Linux 核心工程師,來自阿裡雲系統組。曾就職于 EMC,Sun 中國工程研究院,在存儲系統和 Solaris 核心開發領域工作。 

近幾年來開始研究 Linux 核心,對 Linux 性能優化,記憶體管理子系統有濃厚興趣。

他的聯系方式:

http://oliveryang.net/about

繼續閱讀