具代表性的面試主題

Linux 面試:Load Average 很高但 CPU 使用率很低,如何解釋與排查?

通用困難
OfferCC 編輯團隊發佈 更新

題幹

一台具有 16 個邏輯 CPU 的 Linux 伺服器 Load Average 為 48、36、18,但整體 CPU idle 仍有 72%。這是否代表 CPU 過載?請解釋 Load Average 的意義,並說明如何區分 CPU 排隊、I/O 或核心等待、記憶體壓力與觀測範圍問題。

題幹與適用情境

一台具有 16 個邏輯 CPU 的 Linux 伺服器回應變慢,uptime 顯示 Load Average 為 48 / 36 / 18,但 mpstat 顯示整體 CPU idle 仍有 72%。請判斷這是否代表 CPU 過載,並說明如何找出真正等待的資源。

回答需要解釋 Linux 負載計量中的可執行工作與不可中斷睡眠工作,正確解讀 1、5、15 分鐘三個值,再用工作狀態、Pressure Stall Information(PSI)與子系統指標區分以下情況:

  • CPU 執行佇列確實壅塞;
  • 本機儲存、網路檔案系統、驅動程式或其他核心等待讓工作長時間處於 D 狀態;
  • 記憶體回收或 swap 間接造成等待;
  • 主機層級指標與容器或服務層級指標的範圍不同。

這是一道適合 SRE、DevOps、基礎設施、系統軟體與後端職缺的 Linux 診斷題。16、48、36、18 與 72% 都是虛構的練習資料,不是通用告警門檻。題目假設指標來自同一台主機、同一時間窗;若資料來自不同收集器或不同 cgroup,必須先對齊口徑。

面試官考察點

第一,候選人是否知道 Load Average 不是 CPU 使用率。Linux 的全域負載是可執行工作與不可中斷睡眠工作數量的指數衰減平均。只有前一部分直接表示 CPU 需求,後一部分可能在 CPU 閒置時仍把負載推高。

第二,能否精確解釋三個數字。它們不是最近 1、5、15 分鐘樣本的簡單算術平均,而是具有相應時間常數的指數衰減值。48 > 36 > 18 支持「近期負載正在上升」這個方向性判斷,但不能反推出某一分鐘的精確佇列長度,也不能單獨證明根因。

第三,診斷是否從「總數」走向「組成與等待位置」。好的回答會比較 vmstat 的 r、b,統計 R 與 D 狀態的執行緒,再從 wchan、核心堆疊、PSI 與儲存或網路檔案系統指標,把等待定位到具體資源。只說「執行 top、iostat」沒有說明證據如何改變結論。

第四,候選人是否會處理反例。D 狀態常被工具稱為 disk sleep,但不可中斷等待不只可能來自本機磁碟;NFS、檔案系統、裝置驅動程式與部分核心資源等待也可能出現。%iowait 是 CPU 時間口徑,低 iowait 不能排除工作已經阻塞。

最後看是否有安全的處置與驗證閉環。擴充 CPU、重新啟動、終止行程或升級磁碟,各自只適用於特定證據。修復後需要證明 R/D 工作、PSI、子系統延遲與業務尾端延遲一起恢復,不能只等待 Load Average 緩慢下降。

回答前需要澄清的問題

  • 指標範圍一致嗎? Load Average 通常是主機全域值,而應用程式 CPU 可能只統計一個容器或行程。若範圍不同,先查看主機、cgroup 與服務三層指標,否則「高負載低 CPU」可能只是觀測口徑錯位。
  • CPU idle 是整體平均還是每核心資料? 單一核心、NUMA 節點或受 CPU affinity 限制的工作可能已經排隊,而其他核心閒置。需要查看 mpstat -P ALL、親和性與 cgroup CPU 配額。
  • 變慢的是哪些請求,何時開始? 對齊部署、流量、備份、儲存抖動、掛載變更與記憶體回收時間,才能把主機訊號與使用者影響連起來。
  • R 狀態還是 D 狀態占主導? R 多且 CPU 忙支持 CPU 競爭;D 多且 CPU 閒置支持不可中斷等待。兩者可以同時存在,必須按執行緒與工作負載分組。
  • 底層儲存是什麼? 本機 NVMe、雲端磁碟、區塊裝置、FUSE、NFS 與資料庫遠端呼叫需要不同證據。iostat 看不到一般網路 RPC,NFS 還需要掛載與網路檔案系統指標。
  • 是否有記憶體或虛擬化壓力? swap in/out、直接回收、major fault、宿主機 steal time 與 cgroup 限制會改變診斷優先順序。
  • 能否讀取工作堆疊? /proc/12345/stack、部分 wchan 與行程 I/O 資料可能受權限限制。正式環境排查要使用最小必要權限,並先做低開銷取樣。

30 秒回答框架

「Load Average 不是 CPU 百分比。Linux 統計可執行工作與不可中斷睡眠工作的數量,並計算 1、5、15 分鐘時間常數的指數衰減平均。16 個邏輯 CPU 上負載 48 只能說明有很多活躍或不可中斷等待的工作;CPU 仍有 72% idle,不能直接斷言 CPU 飽和。

我會先確認指標範圍與每核心使用率,再用 vmstat 看可執行佇列 r 與阻塞工作 b,統計執行緒的 R/D 狀態。R 多、CPU PSI 高且 CPU 忙,才像 CPU 排隊;D 多、I/O PSI 高時,再用 wchan、工作堆疊、pidstat、iostat、NFS 與核心日誌定位等待資源。若 memory PSI、swap 與 major fault 同時升高,就轉查記憶體壓力。修復後同時驗證業務 p99、R/D 數量、PSI 與子系統延遲,不只等待負載數字下降。」

分步驟深入解答

第一步:先把 Load Average 拆成兩個來源

Linux 核心計算全域負載時,核心輸入可以概括為:

nr_running + nr_uninterruptible

nr_running 包含正在 CPU 上執行,以及已可執行、等待排程的工作;nr_uninterruptible 表示不可中斷睡眠工作。/proc/loadavg 的前三項是這組活躍工作數量的 1、5、15 分鐘負載值。第四項形如 7/1280,前一個數字是目前可執行的排程實體數量,後一個是目前存在的排程實體總數;第五項是最近建立行程的 PID。

因此,「負載 48」不是「CPU 使用率 300%」,也不是某一時刻恰好有 48 個行程排隊。它是經過平滑處理的工作數量訊號。將負載除以邏輯 CPU 數,只能作為純 CPU 型負載的粗略飽和提示;D 狀態工作較多時,這個比值不再表示 CPU 佇列程度。

核心按固定週期更新指數衰減平均。新樣本權重較高,舊樣本逐漸衰減,所以 48 / 36 / 18 表示近期活躍工作比更早時期多。即使根因已消失,15 分鐘值也會落後;恢復判斷應優先看即時工作狀態、PSI 與業務指標。

第二步:確認範圍、每核心使用率與即時佇列

先做一組低開銷取樣,並保留時間戳記:

bash
nproc
uptime
cat /proc/loadavg
vmstat 1 10
mpstat -P ALL 1 10

vmstat 第一行通常是自開機以來的平均,診斷目前問題時應看後續取樣。關鍵欄位如下:

  • r:可執行工作數量;持續明顯高於可用 CPU 並伴隨 CPU busy,支持 CPU 排隊;
  • b:處於不可中斷睡眠的工作數量;持續升高時優先調查等待資源;
  • us、sy、id、wa、st:區分使用者態、核心態、閒置、I/O wait 與虛擬機被搶占時間;
  • si、so:swap in/out 活動,需要與 memory PSI 和 fault 一起判斷。

整體 72% idle 仍可能掩蓋單核心熱點。若一個序列執行緒固定在 CPU 3,CPU 3 可以接近飽和,而其他 15 個 CPU 大多閒置。此時查看每核心使用率、工作親和性、容器 CPU 配額與 throttling,比盲目增加整台主機 CPU 更有區分力。

第三步:按執行緒統計 R 與 D,找出等待點

行程內的多個執行緒都會參與負載計量,因此要使用執行緒檢視:

bash
ps -eLo state,pid,tid,ppid,wchan:32,comm --sort=state
ps -eLo state= | sort | uniq -c

R 表示正在執行或可執行。D 表示不可中斷睡眠;訊號通常要等工作離開該等待後才能生效,所以反覆執行 kill -9 既不能立即釋放等待中的核心資源,也會破壞現場。

對集中出現的 D 狀態執行緒,按命令、父行程、cgroup 與 wchan 分組。wchan 顯示執行緒在核心中睡眠的位置,能把範圍縮小到區塊 I/O、NFS、檔案系統或驅動程式路徑。權限允許時,再讀取代表性執行緒的核心堆疊:

bash
cat /proc/12345/stack
cat /proc/12345/wchan

單一函式名稱仍不是根因。相同 wchan 大量聚集、同一時間對應子系統延遲與業務變慢,才能形成較強證據。D 狀態也不能自動歸因於應用程式發起大量 I/O;裝置故障、遠端掛載失聯或核心路徑卡住,都可能讓少量請求累積成大量等待執行緒。

第四步:用 PSI 判斷哪一類資源讓工作停止推進

PSI 直接量化 CPU、記憶體與 I/O 爭用造成的停頓時間:

bash
for resource in cpu io memory; do
  echo "[$resource]"
  cat /proc/pressure/"$resource"
done

some 表示至少有部分工作因該資源停頓的時間占比,full 表示所有非 idle 工作同時停頓的時間占比;系統層級 CPU full 保留為零,不應用它判斷 CPU 飽和。avg10、avg60、avg300 分別提供近 10、60、300 秒趨勢,total 是累計停頓微秒數。

PSI 與 Load Average 回答不同問題:Load Average 告訴你有多少活躍或不可中斷等待工作,PSI 告訴你工作負載有多少時間無法推進。兩者結合能避免「負載高就擴 CPU」的誤判。使用 cgroup v2 時,還應讀取目標 cgroup 的 cpu.pressure、io.pressure 與 memory.pressure,把服務本身壓力與主機雜訊分開。

可以用以下矩陣組織證據:

觀測組合首要假設下一步證據
CPU busy 高、r 高、CPU PSI 高CPU 執行佇列競爭每核心熱點、CPU profile、親和性與配額
CPU idle 高、b/D 多、I/O PSI 高I/O 或核心不可中斷等待wchan/堆疊、裝置或 NFS 延遲、核心日誌
memory PSI 高、si/so 或 major fault 增加記憶體回收或 swap 壓力cgroup memory、工作集、回收與儲存讀寫
主機負載高、目標 cgroup PSI 低範圍錯位或其他租戶影響按 cgroup/行程歸屬拆分工作與資源

這張表是調查起點,不是自動根因判定器。CPU、記憶體與 I/O 壓力可能形成回饋,例如記憶體回收引發檔案讀寫,再把執行緒推入 D 狀態。

第五步:進入對應子系統,不把所有等待都稱為「磁碟慢」

若證據指向區塊裝置,觀察裝置吞吐、延遲、佇列與錯誤:

bash
pidstat -d -p ALL 1 10
iostat -xz 1 10
dmesg -T | tail -200

pidstat 協助定位發起 I/O 的行程,iostat 報告裝置與分割區負載。任何欄位都需要結合裝置類型與基線解讀;例如裝置 %util 不能跨所有儲存架構使用同一個飽和門檻。核心日誌中的 timeout、reset、檔案系統錯誤或裝置脫離,比單獨的高佇列更接近故障原因。

若 wchan 或掛載點指向 NFS、FUSE 或網路儲存,要檢查掛載狀態、nfsiostat、用戶端重傳、網路延遲與伺服器端健康。一般 HTTP 或資料庫 RPC 等待通常處於可中斷睡眠,不一定進入 Linux Load Average;因此還需要把應用程式追蹤、連線池與相依服務延遲放進同一時間軸。

若 memory PSI、swap 或 major fault 上升,繼續檢查 cgroup 記憶體事件、匿名與檔案工作集、直接回收和 swap 裝置。只增加磁碟效能可能降低 swap 代價,卻沒有修正工作集超過記憶體預算的原因。

第六步:根據證據止損,並驗證因果關係

處置要對應已確認的等待資源:

  • CPU 佇列競爭:限制入口、降低並行度或批次工作優先權,解除錯誤親和性,必要時按實測容量擴充 CPU;
  • 儲存或 NFS 故障:停止繼續放大 I/O,切換健康副本或掛載路徑,修復裝置、網路或伺服器端;
  • 記憶體壓力:限制工作集與並行度,停止造成 thrashing 的工作,在相容的容量邊界內擴充記憶體;
  • 範圍錯位:先隔離雜訊工作負載或修正 cgroup 配額,再評估目標服務是否需要擴充。

重新啟動可能清除累積工作,也可能遺失關鍵堆疊與日誌;若底層資源仍不可用,新行程會再次阻塞。採取動作前保存代表性 PID、執行緒狀態、wchan、PSI 與子系統快照,並寫下預期變化。

驗收至少包含:業務 p95/p99 與錯誤率恢復;R/D 數量回到基線;對應 PSI 趨勢下降;裝置、NFS、記憶體或 CPU 指標恢復;佇列與積壓被安全處理。Load Average 的指數衰減會產生延遲,所以它是恢復證據之一,不是關閉事故的唯一門檻。

高品質示範回答

「我不會因為 16 個 CPU 上負載 48 就直接說 CPU 過載。Linux Load Average 平滑統計正在執行或等待 CPU 的工作,以及不可中斷睡眠工作。CPU idle 還有 72%,代表負載很可能包含大量 D 狀態等待,或整體平均掩蓋了單核心、配額或指標範圍問題。

48 / 36 / 18 是三個指數衰減平均,方向上表示近期活躍工作增加,不是三個簡單時間窗的算術平均,也不能告訴我根因。我先確認 Load、CPU 與業務延遲來自同一主機和時間窗,再看 mpstat -P ALL,排除單核心熱點與 steal time。

下一步用 vmstat 1 看 r 與 b。如果 r 持續高、CPU busy 與 CPU PSI 也高,我會從 CPU profile、親和性與 cgroup throttling 排查。如果 b 高、D 狀態執行緒很多但 CPU 仍閒置,我會按命令與 wchan 彙整執行緒,選擇代表性執行緒查看 /proc/12345/stack,再與 I/O PSI 對齊。

假設大量執行緒都停在 NFS 相關等待,I/O PSI 同時上升,本機區塊裝置的 iostat 卻正常,我會轉查掛載、用戶端重傳、網路與 NFS 伺服器端,不會升級本機雲端磁碟。止損可能是停止相關批次工作、把讀取切到健康副本或摘除故障節點;直接反覆終止 D 狀態行程通常不會立即生效。

修復後,我會驗證業務尾端延遲與錯誤率、R/D 執行緒數、cgroup 與主機 PSI、NFS 延遲和積壓都恢復。1、5、15 分鐘負載會隨時間衰減,因此即使 15 分鐘值仍高,只要即時等待與使用者結果已穩定,也不應為追求一個立刻變小的數字繼續做高風險操作。」

常見錯誤

  • 把 Load Average 當 CPU 使用率 → 它統計工作數量,並包含不可中斷睡眠 → 先拆分 r 與 b、R 與 D,再判斷 CPU 競爭。
  • 看到負載超過 CPU 數就宣布過載 → 這個規則只對 CPU 型負載有粗略提示價值 → 結合 CPU busy、CPU PSI 與可執行佇列。
  • 把 1、5、15 分鐘值當簡單窗口平均 → Linux 使用指數衰減,舊樣本會逐漸保留 → 只用三值判斷方向,並用即時指標確認目前狀態。
  • 把所有 D 狀態都歸因於本機磁碟 → NFS、檔案系統、驅動程式與其他核心等待也可能進入不可中斷睡眠 → 沿 wchan、堆疊與對應子系統指標定位。
  • iowait 低就排除 I/O → iowait 是 CPU 時間統計,不等於等待工作數量 → 查看 D 狀態、I/O PSI、裝置與遠端儲存延遲。
  • 只看主機平均 CPU → 單核心熱點、親和性、配額或其他 cgroup 會被平均掩蓋 → 比較每核心、主機與目標 cgroup。
  • 反覆 kill -9 卡住的工作 → 訊號要等不可中斷等待返回後才會處理,現場還可能被破壞 → 先保存證據並修復被等待的資源。
  • 把一條 wchan 當成根因 → 它只顯示目前核心睡眠位置 → 要求大量工作聚集、時間相關性與子系統異常互相印證。
  • 只等 Load Average 歸零才宣布恢復 → 指數衰減會落後,正常系統也不要求負載為零 → 以使用者結果、即時工作、PSI 與資源指標共同驗收。

追問及應對

追問一:CPU idle 很高,為什麼 %iowait 也可能很低?

%iowait 表示 CPU 處於 idle 且系統認為有未完成 I/O 的時間比例,它是 CPU 記帳口徑。工作可以阻塞在 NFS、驅動程式或其他不可中斷核心等待,而 CPU 同時執行其他工作或保持一般 idle;多核心系統的彙整也會稀釋局部現象。應用 D 狀態數量、I/O PSI、wchan 與子系統延遲驗證,不能用低 iowait 單獨排除 I/O 或核心等待。

追問二:容器裡看到的 Load Average 能代表這個容器嗎?

不能預設代表。負載值與 /proc 的可見範圍取決於宿主機、PID namespace、執行環境與監控實作;應用程式 CPU 指標又可能依 cgroup 統計。應同時讀取宿主機與目標 cgroup 的 CPU、I/O、memory PSI 和配額事件,並把執行緒歸屬到 cgroup。若主機負載很高但目標 cgroup 沒有壓力,擴充該服務可能沒有收益。

追問三:負載 48、CPU idle 72%,是否一定存在大量 D 狀態?

不一定。還可能是指標不同步、CPU 平均掩蓋單核心熱點、工作受 affinity 或 cgroup 配額限制,或負載剛從高點下降而指數平均尚未衰減。檢查目前 /proc/loadavg 的 runnable 數、vmstat r/b、每核心使用率、R/D 執行緒數與收集時間,才能確定組成。

追問四:為什麼 D 狀態行程有時連 kill -9 都不消失?

不可中斷睡眠的設計目標,是讓某些核心操作在關鍵階段不被一般訊號中斷。SIGKILL 可以被標記為待處理,但工作通常要先從等待返回,排程到能處理退出的路徑,行程才會消失。修復裝置、掛載、網路或驅動程式等待,往往比重複發送訊號更重要;必要的主機重新啟動應依資料完整性與服務冗餘評估。

追問五:如何為 Load Average 設定告警?

不要複製固定的「負載大於 CPU 數」門檻。CPU 型服務應組合 load、可執行佇列、CPU PSI、使用率與 cgroup throttling;I/O 型服務應關注 I/O PSI、D 狀態、裝置或遠端儲存延遲與業務 SLO。告警門檻來自正常基線、持續時間、擴充速度與使用者影響,而且要標註指標範圍。

公開來源

同類題目