Linux 效能分析的前 60 秒

Brendan Gregg發表於2016-01-24
作者: Brendan Gregg 譯者: spacewander

| 2016-01-24 08:34   收藏: 6    

為了解決效能問題,你登入了一臺 Linux 伺服器,在最開始的一分鐘內需要檢視什麼?

在 Netflix 我們有一個龐大的 EC2 Linux 叢集,還有非常多的效能分析工具來監控和調查它的效能。其中包括用於雲監控的Atlas,用於例項按需分析的 Vector。即使這些工具幫助我們解決了大多數問題,我們有時還是得登入 Linux 例項,執行一些標準的 Linux 效能工具來解決問題。

在這篇文章裡,Netflix Performance Engineering 團隊將使用居家常備的 Linux 標準命令列工具,演示在效能調查最開始的60秒裡要乾的事,

最開始的60秒......

執行下面10個命令,你可以在60秒內就對系統資源的使用情況和程式的執行狀況有大體上的瞭解。無非是先檢視錯誤資訊和飽和指標,再看下資源的使用量。這裡“飽和”的意思是,某項資源供不應求,已經造成了請求佇列的堆積,或者延長了等待時間。

uptime
dmesg | tail
vmstat 1
mpstat -P ALL 1
pidstat 1
iostat -xz 1
free -m
sar -n DEV 1
sar -n TCP,ETCP 1
top

有些命令需要你安裝 sysstat 包。(譯註:指 mpstat, pidstat, iostat和sar,用包管理器直接安裝 sysstat 即可) 這些命令所提供的指標能夠幫助你實踐 USE 方法:這是一種用於定位效能瓶頸的方法論。你可以以此檢查所有資源(CPU,記憶體,硬碟,等等)的使用量是否飽和,以及是否存在錯誤。同時請留意上一次檢查正常的時刻,這將幫助你減少待分析的物件,並指明調查的方向。(譯註:USE 方法,就是檢查每一項資源的使用量utilization飽和saturation錯誤error

接下來的章節裡我們將結合實際例子講解這些命令。如果你想了解更多的相關資訊,請檢視它們的 man page。

1. uptime

$ uptime
 23:51:26 up 21:31,  1 user,  load average: 30.02, 26.43, 19.02

這個命令顯示了要執行的任務(程式)數,透過它能夠快速瞭解系統的平均負載。在 Linux 上,這些數值既包括正在或準備執行在 CPU 上的程式,也包括阻塞在不可中斷 I/O(通常是磁碟 I/O)上的程式。它展示了資源負載(或需求)的大致情況,不過進一步的解讀還有待其它工具的協助。對它的具體數值不用太較真。

最右的三個數值分別是1分鐘、5分鐘、15分鐘系統負載的移動平均值。它們共同展現了負載隨時間變動的情況。舉個例子,假設你被要求去檢查一個出了問題的伺服器,而它最近1分鐘的負載遠遠低於15分鐘的負載,那麼你很可能已經撲了個空。

在上面的例子中,負載均值最近呈上升態勢,其中1分鐘值高達30,而15分鐘值僅有19。這種現象有許多種解釋,很有可能是對 CPU 的爭用;該系列的第3個和第4個命令——vmstatmpstat——可以幫助我們進一步確定問題所在。

2. dmesg | tail

$ dmesg | tail
[1880957.563150] perl invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0
[...]
[1880957.563400] Out of memory: Kill process 18694 (perl) score 246 or sacrifice child
[1880957.563408] Killed process 18694 (perl) total-vm:1972392kB, anon-rss:1953348kB, file-rss:0kB
[2320864.954447] TCP: Possible SYN flooding on port 7001. Dropping request.  Check SNMP counters.

這個命令顯示了最新的10個系統資訊,如果有的話。注意會導致效能問題的錯誤資訊。上面的例子裡就包括對過多佔用記憶體的某程式的死刑判決,還有丟棄 TCP 請求的公告。

不要漏了這一步!檢查dmesg總是值得的。

3. vmstat 1

$ vmstat 1
procs ---------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
34  0    0 200889792  73708 591828    0    0     0     5    6   10 96  1  3  0  0
32  0    0 200889920  73708 591860    0    0     0   592 13284 4282 98  1  1  0  0
32  0    0 200890112  73708 591860    0    0     0     0 9501 2154 99  1  0  0  0
32  0    0 200889568  73712 591856    0    0     0    48 11900 2459 99  0  0  0  0
32  0    0 200890208  73712 591860    0    0     0     0 15898 4840 98  1  1  0  0
^C

vmstat(8),是 “virtual memory stat” 的簡稱,幾十年前就已經包括在 BSD 套件之中,一直以來都是居家常備的工具。它會逐行輸出伺服器關鍵資料的統計結果。

透過指定1作為 vmstat 的輸入引數,它會輸出每一秒內的統計結果。(在我們當前使用的)vmstat 輸出的第一行資料是從啟動到現在的平均資料,而不是前一秒的資料。所以我們可以跳過第一行,看看後面幾行的情況。

檢查下面各列:

r:等待 CPU 的程式數。該指標能更好地判定 CPU 是否飽和,因為它不包括 I/O。簡單地說,r 值高於 CPU 數時就意味著飽和。

free:空閒的記憶體千位元組數。如果你數不清有多少位,就說明系統記憶體是充足的。接下來要講到的第7個命令,free -m,能夠更清楚地說明空閒記憶體的狀態。

siso:交換分割槽換入和換出。如果它們不為零,意味著記憶體已經不足,開始動用交換空間的存糧了。

ussyidwast:它們是所有 CPU 的使用百分比。它們分別表示 使用者態用時user time系統態用時system time(處於核心態的時間),空閒idleI/O 等待wait I/O偷去的時間steal time(被其它租戶,或者是租戶自己的 Xen 隔離裝置驅動域isolated driver domain所佔用的時間)。

透過相加 us 和 sy 的百分比,你可以確定 CPU 是否處於忙碌狀態。一個持續不變的 I/O 等待意味著瓶頸在硬碟上,這種情況往往伴隨著 CPU 的空閒,因為任務都卡在磁碟 I/O 上了。你可以把 I/O 等待當作 CPU 空閒的另一種形式,它額外給出了 CPU 空閒的線索。

I/O 處理同樣會消耗系統時間。一個高於20%的平均系統時間,往往值得進一步發掘:也許系統花在 I/O 的時間太長了。

在上面的例子中,CPU 基本把時間花在使用者態裡面,意味著跑在上面的應用佔用了大部分時間。此外,CPU 平均使用率在90%之上。這不一定是個問題;檢查下“r”列,看看是否飽和了。

4. mpstat -P ALL 1

$ mpstat -P ALL 1
Linux 3.13.0-49-generic (titanclusters-xxxxx)  07/14/2015  _x86_64_ (32 CPU)

07:38:49 PM  CPU   %usr  %nice   %sys %iowait   %irq  %soft  %steal  %guest  %gnice  %idle
07:38:50 PM  all  98.47   0.00   0.75    0.00   0.00   0.00    0.00    0.00    0.00   0.78
07:38:50 PM    0  96.04   0.00   2.97    0.00   0.00   0.00    0.00    0.00    0.00   0.99
07:38:50 PM    1  97.00   0.00   1.00    0.00   0.00   0.00    0.00    0.00    0.00   2.00
07:38:50 PM    2  98.00   0.00   1.00    0.00   0.00   0.00    0.00    0.00    0.00   1.00
07:38:50 PM    3  96.97   0.00   0.00    0.00   0.00   0.00    0.00    0.00    0.00   3.03
[...]

這個命令顯示每個 CPU 的時間使用百分比,你可以用它來檢查 CPU 是否存在負載不均衡。單個過於忙碌的 CPU 可能意味著整個應用只有單個執行緒在工作。

5. pidstat 1

$ pidstat 1
Linux 3.13.0-49-generic (titanclusters-xxxxx)  07/14/2015    _x86_64_    (32 CPU)

07:41:02 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
07:41:03 PM     0         9    0.00    0.94    0.00    0.94     1  rcuos/0
07:41:03 PM     0      4214    5.66    5.66    0.00   11.32    15  mesos-slave
07:41:03 PM     0      4354    0.94    0.94    0.00    1.89     8  java
07:41:03 PM     0      6521 1596.23    1.89    0.00 1598.11    27  java
07:41:03 PM     0      6564 1571.70    7.55    0.00 1579.25    28  java
07:41:03 PM 60004     60154    0.94    4.72    0.00    5.66     9  pidstat

07:41:03 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
07:41:04 PM     0      4214    6.00    2.00    0.00    8.00    15  mesos-slave
07:41:04 PM     0      6521 1590.00    1.00    0.00 1591.00    27  java
07:41:04 PM     0      6564 1573.00   10.00    0.00 1583.00    28  java
07:41:04 PM   108      6718    1.00    0.00    0.00    1.00     0  snmp-pass
07:41:04 PM 60004     60154    1.00    4.00    0.00    5.00     9  pidstat
^C

pidstat看上去就像top,不過top的輸出會覆蓋掉之前的輸出,而pidstat的輸出則新增在之前的輸出的後面。這有利於觀察資料隨時間的變動情況,也便於把你看到的內容複製貼上到調查報告中。

上面的例子表明,CPU 主要消耗在兩個 java 程式上。%CPU列是在各個 CPU 上的使用量的總和;1591%意味著 java 程式消耗了將近16個 CPU。

6. iostat -xz 1

$ iostat -xz 1
Linux 3.13.0-49-generic (titanclusters-xxxxx)  07/14/2015  _x86_64_ (32 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          73.96    0.00    3.73    0.03    0.06   22.21

Device:   rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
xvda        0.00     0.23    0.21    0.18     4.52     2.08    34.37     0.00    9.98   13.80    5.42   2.44   0.09
xvdb        0.01     0.00    1.02    8.94   127.97   598.53   145.79     0.00    0.43    1.78    0.28   0.25   0.25
xvdc        0.01     0.00    1.02    8.86   127.79   595.94   146.50     0.00    0.45    1.82    0.30   0.27   0.26
dm-0        0.00     0.00    0.69    2.32    10.47    31.69    28.01     0.01    3.23    0.71    3.98   0.13   0.04
dm-1        0.00     0.00    0.00    0.94     0.01     3.78     8.00     0.33  345.84    0.04  346.81   0.01   0.00
dm-2        0.00     0.00    0.09    0.07     1.35     0.36    22.50     0.00    2.55    0.23    5.62   1.78   0.03
[...]
^C

這個命令可以弄清塊裝置(磁碟)的狀況,包括工作負載和處理效能。注意以下各項:

r/sw/srkB/swkB/s:分別表示每秒裝置讀次數,寫次數,讀的 KB 數,寫的 KB 數。它們描述了磁碟的工作負載。也許效能問題就是由過高的負載所造成的。

await:I/O 平均時間,以毫秒作單位。它是應用中 I/O 處理所實際消耗的時間,因為其中既包括排隊用時也包括處理用時。如果它比預期的大,就意味著裝置飽和了,或者裝置出了問題。

avgqu-sz:分配給裝置的平均請求數。大於1表示裝置已經飽和了。(不過有些裝置可以並行處理請求,比如由多個磁碟組成的虛擬裝置)

%util:裝置使用率。這個值顯示了裝置每秒內工作時間的百分比,一般都處於高位。低於60%通常是低效能的表現(也可以從 await 中看出),不過這個得看裝置的型別。接近100%通常意味著飽和。

如果某個儲存裝置是由多個物理磁碟組成的邏輯磁碟裝置,100%的使用率可能只是意味著 I/O 佔用。

請牢記於心,磁碟 I/O 效能低不一定是個問題。應用的 I/O 往往是非同步的(比如預讀read-ahead寫緩衝buffering for writes),所以不一定會被阻塞並遭受延遲。

7. free -m

$ free -m
             total       used       free     shared    buffers     cached
Mem:        245998      24545     221453         83         59        541
-/+ buffers/cache:      23944     222053
Swap:            0          0          0

右邊的兩列顯示:

buffers:用於塊裝置 I/O 的緩衝區快取

cached:用於檔案系統的頁快取

它們的值接近於0時,往往導致較高的磁碟 I/O(可以透過 iostat 確認)和糟糕的效能。上面的例子裡沒有這個問題,每一列都有好幾 M 呢。

比起第一行,-/+ buffers/cache提供的記憶體使用量會更加準確些。Linux 會把暫時用不上的記憶體用作快取,一旦應用需要的時候立刻重新分配給它。所以部分被用作快取的記憶體其實也算是空閒記憶體,第二行以此修訂了實際的記憶體使用量。為了解釋這一點, 甚至有人專門建了個網站: LinuxAteMyRam.com

如果你在 Linux 上安裝了 ZFS,正如我們在一些服務上所做的,這一點會變得更加迷惑,因為 ZFS 它自己的檔案系統快取不算入free -m。有時系統看上去已經沒有多少空閒記憶體可用了,其實記憶體都待在 ZFS 的快取裡呢。

8. sar -n DEV 1

$ sar -n DEV 1
Linux 3.13.0-49-generic (titanclusters-xxxxx)  07/14/2015     _x86_64_    (32 CPU)

12:16:48 AM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
12:16:49 AM      eth0  18763.00   5032.00  20686.42    478.30      0.00      0.00      0.00      0.00
12:16:49 AM        lo     14.00     14.00      1.36      1.36      0.00      0.00      0.00      0.00
12:16:49 AM   docker0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00

12:16:49 AM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
12:16:50 AM      eth0  19763.00   5101.00  21999.10    482.56      0.00      0.00      0.00      0.00
12:16:50 AM        lo     20.00     20.00      3.25      3.25      0.00      0.00      0.00      0.00
12:16:50 AM   docker0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
^C

這個命令可以用於檢查網路流量的工作負載:rxkB/s 和 txkB/s,以及它是否達到限額了。上面的例子中,eth0接收的流量達到 22Mbytes/s,也即 176Mbits/sec(限額是 1Gbit/sec)

我們用的版本中還提供了%ifutil作為裝置使用率(接收和傳送兩者中的最大值)的指標。我們也可以用 Brendan 的 nicstat計量這個值。一如nicstatsar顯示的這個值不一定是對的,在這個例子裡面就沒能正常工作(0.00)。

9. sar -n TCP,ETCP 1

$ sar -n TCP,ETCP 1
Linux 3.13.0-49-generic (titanclusters-xxxxx)  07/14/2015    _x86_64_    (32 CPU)

12:17:19 AM  active/s passive/s    iseg/s    oseg/s
12:17:20 AM      1.00      0.00  10233.00  18846.00

12:17:19 AM  atmptf/s  estres/s retrans/s isegerr/s   orsts/s
12:17:20 AM      0.00      0.00      0.00      0.00      0.00

12:17:20 AM  active/s passive/s    iseg/s    oseg/s
12:17:21 AM      1.00      0.00   8359.00   6039.00

12:17:20 AM  atmptf/s  estres/s retrans/s isegerr/s   orsts/s
12:17:21 AM      0.00      0.00      0.00      0.00      0.00
^C

這個命令顯示一些關鍵TCP指標的彙總。其中包括:

active/s:本地每秒建立的 TCP 連線數(比如 concept() 建立的)

passive/s:遠端每秒建立的 TCP 連線數(比如 accept() 建立的)

retrans/s:每秒 TCP 重傳次數

主動連線數active被動連線數passive通常可以用來粗略地描述系統負載。可以認為主動連線是對外的,而被動連線是對內的,雖然嚴格來說不完全是這個樣子。(比如,一個從 localhost 到 localhost 的連線)

重傳是網路或系統問題的一個訊號;它可能是不可靠的網路(比如公網)所造成的,也有可能是伺服器已經過載並開始丟包。在上面的例子中,每秒只建立一個新的 TCP 連線。

10. top

$ top
top - 00:15:40 up 21:56,  1 user,  load average: 31.09, 29.87, 29.92
Tasks: 871 total,   1 running, 868 sleeping,   0 stopped,   2 zombie
%Cpu(s): 96.8 us,  0.4 sy,  0.0 ni,  2.7 id,  0.1 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:  25190241+total, 24921688 used, 22698073+free,    60448 buffers
KiB Swap:        0 total,        0 used,        0 free.   554208 cached Mem

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 20248 root      20   0  0.227t 0.012t  18748 S  3090  5.2  29812:58 java
  4213 root      20   0 2722544  64640  44232 S  23.5  0.0 233:35.37 mesos-slave
 66128 titancl+  20   0   24344   2332   1172 R   1.0  0.0   0:00.07 top
  5235 root      20   0 38.227g 547004  49996 S   0.7  0.2   2:02.74 java
  4299 root      20   0 20.015g 2.682g  16836 S   0.3  1.1  33:14.42 java
     1 root      20   0   33620   2920   1496 S   0.0  0.0   0:03.82 init
     2 root      20   0       0      0      0 S   0.0  0.0   0:00.02 kthreadd
     3 root      20   0       0      0      0 S   0.0  0.0   0:05.35 ksoftirqd/0
     5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H
     6 root      20   0       0      0      0 S   0.0  0.0   0:06.94 kworker/u256:0
     8 root      20   0       0      0      0 S   0.0  0.0   2:38.05 rcu_sched
    

top命令包括很多我們之前檢查過的指標。它適合用來檢視相比於之前的命令輸出的結果,負載有了哪些變動。

不能清晰顯示資料隨時間變動的情況,這是top的一個缺點。相較而言,vmstatpidstat的輸出不會覆蓋掉之前的結果,因此更適合檢視資料隨時間的變動情況。另外,如果你不能及時暫停top的輸出(Ctrl-s 暫停,Ctrl-q 繼續),也許某些關鍵線索會湮滅在新的輸出中。

在這之後...

有很多工具和方法論有助於你深入地發掘問題。Brendan 在2015年 Velocity 大會上的 Linux Performance Tools tutorial 中列出超過40個命令,覆蓋了觀測、基準測試、調優、靜態效能調優、分析profile,和追蹤tracing多個方面。

Linux 效能分析的前 60 秒

相關文章