一文理解 Linux 平均負載,附排查工具

作者:大胖猴 

鏈接:https://www.cnblogs.com/xzkzzz/p/11164089.html

什麼是平均負載

平均負載可以對於我們來說及熟悉又陌生,但我們問平均負載是什麼,但大部分人都回答說平均負載不就是單位時間內 CPU 使用率嗎?其實並不是這樣的,如果可以的話,可以 man uptime 來了解一下平均負載的詳細信息。

簡單的說平均負載是指單位時間內,系統處於可運行狀態和不可中斷狀態的平均進程數,也就是說平均活躍進程數,它和 CPU 使用率並沒有直接關係。這裏解釋一下可運行狀態和不可中斷這兩個詞。

比如,當一個進程向磁盤讀寫數據時,爲了保證數據的一致性,在得到磁盤迴復前,它是不能被其他進程中斷或者打斷的,這個時候的進程處於不可中斷狀態,如果此時的進程被打斷了,就容易出現磁盤數據和進程數據不一致的問題。

所以,不可中斷狀態實際上是系統進程和硬件設備的一種保護機制。

因此,你可以簡單理解爲,平均負載就是平均活躍進程數。平均活躍進程數,直觀上的理解就是單位時間內的活躍進程數,但它實際上是活躍進程數的指數衰減平均值。既然是平均活躍進程數,那麼理想狀態,就是每個 CPU 上都剛好運行着一個進程,這樣每個 CPU 都會得到充分的利用。例如平均負載爲 2 時,意味着什麼呢?

平均負載和 CPU 使用率

現實工作中,我們經常容易把平均負載和 CPU 使用率混淆,所以在這裏,我也做一個分區。

可能你會疑惑,既然平均負載代表的是活躍進程數,那平均負載高了,不就意味着 CPU 使用率高嗎?

我們還是要回到平均負載的含義上來,平均負載是指單位時間內,處於可運行狀態和不可中斷狀態的進程數,所以,它不僅包括了正常使用 CPU 的進程,還包括了等待 CPU 和等待 I/O 的進程。

而 CPU 使用率,是單位時間內 CPU 的繁忙情況的統計,跟平均負載並不一定完全對應,例如:

平均負載案例

這裏我們需要安裝幾個工具 sysstat、stress、stress-ng

這裏 Centos 的 sysstat 版本會老一點,最好升級到最新版本。手動 rpm 安裝或者源碼安裝

場景一、CPU 密集型

1、運行一個 stress 命令,模擬一個 CPU 使用率 100% 場景

$ stress --cpu 1 --timeout 600

2、開啓第二個終端,uptime 查看平均負載的變化情況

$ watch -d uptime
 09:40:35 up 80 days, 18:41,  2 users,  load average: 1.62, 1.10, 0.87

3、開啓第三個終端,mpstat 查看 CPU 使用率的變化情況

$ mpstat -P ALL 5 20
10:06:37 AM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
10:06:42 AM  all   31.50    0.00    0.35    0.00    0.00    0.00    0.00    0.00    0.00   68.15
10:06:42 AM    0    1.20    0.00    0.80    0.00    0.00    0.00    0.00    0.00    0.00   98.00
10:06:42 AM    1    7.21    0.00    0.40    0.00    0.00    0.00    0.00    0.00    0.00   92.38
10:06:42 AM    2  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
10:06:42 AM    3   17.43    0.00    0.20    0.00    0.00    0.00    0.00    0.00    0.00   82.36
# -P ALL 表示監控所有CPU,後面數字5 表示間隔5秒輸出一次數據

從第二個終端可以看到,1 分鐘平均負載增加到 1.62,從第三個終端我們可以看到有一個 CPU 使用率 100%,但 iowait 爲 0,這說明平均負載的升高正式由 CPU 使用率爲 100%

那我們查看是那個進程導致了 CPU 使用率爲 100% 呢?我們可以使用 pidstat 來查看:

#每5秒輸出一次數據
$ pidstat -u 5 1 
10:08:41 AM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
10:08:46 AM     0         1    0.20    0.00    0.00    0.00    0.20     0  systemd
10:08:46 AM     0       599    0.00    1.00    0.00    0.20    1.00     0  systemd-journal
10:08:46 AM     0      1043    0.60    0.00    0.00    0.00    0.60     0  rsyslogd
10:08:46 AM     0      6863  100.00    0.00    0.00    0.00  100.00     3  stress
10:08:46 AM     0      7303    0.20    0.20    0.00    0.00    0.40     2  pidstat

從這裏我們可以看到是 stress 這個進程導致的。

場景二、I/O 密集型進程

1、我們使用 stress-ng 命令,但這次模擬 I/O 壓力,既不停執行 sync:

#--hdd表示讀寫臨時文件
#-i 生成幾個worker循環調用sync()產生io壓力
$ stress-ng -i 4 --hdd 1 --timeout 600

2、開啓第二個終端運行 uptime 查看平均負載情況

$ watch -d uptime 
 10:30:57 up 98 days, 19:39,  3 users,  load average: 1.71, 0.75, 0.69

3、開啓第三個終端運行 mpstat 查看 CPU 使用率

$ mpstat -P ALL 5 20
10:32:09 AM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
10:32:14 AM  all    6.80    0.00   33.75   26.16    0.00    0.39    0.00    0.00    0.00   32.90
10:32:14 AM    0    4.03    0.00   69.57   19.91    0.00    0.00    0.00    0.00    0.00    6.49
10:32:14 AM    1   25.32    0.00    9.49    0.00    0.00    0.95    0.00    0.00    0.00   64.24
10:32:14 AM    2    0.24    0.00   10.87   63.04    0.00    0.48    0.00    0.00    0.00   25.36
10:32:14 AM    3    1.42    0.00   36.93   14.20    0.00    0.28    0.00    0.00    0.00   47.16

從這裏可以看到,1 分鐘平均負載會慢慢增加到 1.71,其中一個 CPU 的系統 CPU 使用率升到 63.04。這說明,平均負載的升高是由於 iowait 升高。

那麼我們到底是哪個進程導致的呢?我們使用 pidstat 來查看:

$ pidstat -u 5 1
Average:      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
Average:        0         1    0.00    0.19    0.00    0.00    0.19     -  systemd
Average:        0        10    0.00    0.19    0.00    1.56    0.19     -  rcu_sched
Average:        0       599    0.58    1.75    0.00    0.39    2.33     -  systemd-journal
Average:        0      1043    0.19    0.19    0.00    0.00    0.39     -  rsyslogd
Average:        0      6934    0.00    1.56    0.00    1.17    1.56     -  kworker/2:0-events_power_efficient
Average:        0      7383    0.00    0.39    0.00    0.78    0.39     -  kworker/1:0-events_power_efficient
Average:        0      9411    0.00    0.19    0.00    0.58    0.19     -  kworker/0:0-events
Average:        0      9662    0.00   97.67    0.00    0.19   97.67     -  kworker/u8:0+flush-253:0
Average:        0     10793    0.00    0.97    0.00    1.56    0.97     -  kworker/3:2-mm_percpu_wq
Average:        0     11062    0.00   21.79    0.00    0.19   21.79     -  stress-ng-hdd
Average:        0     11063    0.00    1.95    0.00    1.36    1.95     -  stress-ng-io
Average:        0     11064    0.00    2.72    0.00    0.39    2.72     -  stress-ng-io
Average:        0     11065    0.00    1.36    0.00    1.75    1.36     -  stress-ng-io
Average:        0     11066    0.00    2.72    0.00    0.58    2.72     -  stress-ng-io

可以發現是 stress-ng 導致的

場景三、大量進程的場景

當系統中運行進程超出 CPU 運行能力時,就會出現等待 CPU 的進程。

比如:我們使用 stress, 但這次模擬 8 個進程:

$ stress -c 8 --timeout 600

我們的系統只有 4 顆 CPU,這時候要運行 8 個進程,是明顯不夠的,系統的 CPU 後嚴重過載, 這時候負載值達到了 4 點多:

$  uptime
 10:56:22 up 98 days, 20:05,  3 users,  load average: 4.52, 2.82, 2.67

接着我們運行 pidstat 來查看一下進程的情況:

$ pidstat -u 5 1
Linux 5.0.5-1.el7.elrepo.x86_64 (k8s-m1)     07/11/2019     _x86_64_    (4 CPU)

10:57:33 AM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
10:57:38 AM     0         1    0.20    0.00    0.00    0.00    0.20     1  systemd
10:57:38 AM     0       599    0.00    0.99    0.00    0.20    0.99     2  systemd-journal
10:57:38 AM     0      1043    0.60    0.20    0.00    0.00    0.79     1  rsyslogd
10:57:38 AM     0     12927   51.59    0.00    0.00   48.21   51.59     0  stress
10:57:38 AM     0     12928   44.64    0.00    0.00   54.96   44.64     0  stress
10:57:38 AM     0     12929   45.44    0.00    0.00   54.56   45.44     2  stress
10:57:38 AM     0     12930   45.44    0.00    0.00   54.37   45.44     2  stress
10:57:38 AM     0     12931   51.59    0.00    0.00   48.21   51.59     3  stress
10:57:38 AM     0     12932   48.41    0.00    0.00   51.19   48.41     1  stress
10:57:38 AM     0     12933   45.24    0.00    0.00   54.37   45.24     3  stress
10:57:38 AM     0     12934   48.81    0.00    0.00   50.99   48.81     1  stress
10:57:38 AM     0     13083    0.00    0.40    0.00    0.20    0.40     0  pidstat

可以看出,8 個進程搶佔 4 顆 CPU,每個進程等到 CPU 時間 (%wait) 高達 50%,這些都超出 CPU 計算能力的進程,最終導致 CPU 過載。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Fyc31tHmP5-VOjOn3te_VA