Linux性能分析的前60000毫秒

原文鏈接:http://techblog.netflix.com/2015/11/linux-performance-analysis-in-60s.html
作者是Brendan Gregg, Oracle/Linux系統性能分析方面的大牛。

Linux性能分析的前60000毫秒

爲了解決性能問題,你登入了一臺Linux服務器,在最開始的一分鐘內需要查看什麼?

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

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

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

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

uptimedmesg | tailvmstat 1mpstat -P ALL 1pidstat 1iostat -xz 1free -msar -n DEV 1sar -n TCP,ETCP 1top

有些命令需要你安裝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上的進程,也包括阻塞在uninterruptible 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 st34  0    0 200889792  73708 591828    0    0     0     5    6   10 96  1  3  0  032  0    0 200889920  73708 591860    0    0     0   592 13284 4282 98  1  1  0  032  0    0 200890112  73708 591860    0    0     0     0 9501 2154 99  1  0  0  032  0    0 200889568  73712 591856    0    0     0    48 11900 2459 99  0  0  0  032  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,能夠更清楚地說明空閒內存的狀態。

si,so:Swap-ins和Swap-outs。如果它們不爲零,意味着內存已經不足,開始動用交換空間的存糧了。

us,sy,id,wa,st:它們是所有CPU的使用百分比。它們分別表示user time,system time(處於內核態的時間),idle,wait I/O和steal time(被其它租戶,或者是租戶自己的Xen隔離設備驅動域(isolated driver domain),所佔用的時間)。

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

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

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

4. mpstat -P ALL 1

$ mpstat -P ALL 1Linux 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  %idle07:38:50 PM  all  98.47   0.00   0.75    0.00   0.00   0.00    0.00    0.00    0.00   0.7807:38:50 PM    0  96.04   0.00   2.97    0.00   0.00   0.00    0.00    0.00    0.00   0.9907:38:50 PM    1  97.00   0.00   1.00    0.00   0.00   0.00    0.00    0.00    0.00   2.0007:38:50 PM    2  98.00   0.00   1.00    0.00   0.00   0.00    0.00    0.00    0.00   1.0007: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 1Linux 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  Command07:41:03 PM     0         9    0.00    0.94    0.00    0.94     1  rcuos/007:41:03 PM     0      4214    5.66    5.66    0.00   11.32    15  mesos-slave07:41:03 PM     0      4354    0.94    0.94    0.00    1.89     8  java07:41:03 PM     0      6521 1596.23    1.89    0.00 1598.11    27  java07:41:03 PM     0      6564 1571.70    7.55    0.00 1579.25    28  java07:41:03 PM 60004     60154    0.94    4.72    0.00    5.66     9  pidstat07:41:03 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command07:41:04 PM     0      4214    6.00    2.00    0.00    8.00    15  mesos-slave07:41:04 PM     0      6521 1590.00    1.00    0.00 1591.00    27  java07:41:04 PM     0      6564 1573.00   10.00    0.00 1583.00    28  java07:41:04 PM   108      6718    1.00    0.00    0.00    1.00     0  snmp-pass07: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 1Linux 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.21Device:   rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %utilxvda        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.25xvdc        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.26dm-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.04dm-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.00dm-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/s,w/s,rkB/s,wkB/s:分別表示每秒設備讀次數,寫次數,讀的KB數,寫的KB數。它們描述了磁盤的工作負載。也許性能問題就是由過高的負載所造成的。

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

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

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

如果某個存儲設備是由多個物理磁盤組成的邏輯磁盤設備,100%的使用率可能只是意味着I/O佔用

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

7. free -m

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

右邊的兩列顯示:
buffers:用於塊設備I/O的緩衝區緩存
cached:用於文件系統的頁緩存
它們的值接近於0時,往往導致較高的磁盤I/O(可以通過iostat確認)和糟糕的性能。上面的例子裏沒有這個問題,每一列都有好幾M呢。

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

如果你在Linux上安裝了ZFS,正如我們在一些服務上所做的,這一點會變得更加迷惑,因爲ZFS它自己的文件系統緩存不算入free -m。有時系統看上去已經沒有多少空閒內存可用了,其實內存都待在ZFS的緩存裏呢。

8. sar -n DEV 1

$ sar -n DEV 1Linux 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   %ifutil12:16:49 AM      eth0  18763.00   5032.00  20686.42    478.30      0.00      0.00      0.00      0.0012:16:49 AM        lo     14.00     14.00      1.36      1.36      0.00      0.00      0.00      0.0012:16:49 AM   docker0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.0012:16:49 AM     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil12:16:50 AM      eth0  19763.00   5101.00  21999.10    482.56      0.00      0.00      0.00      0.0012:16:50 AM        lo     20.00     20.00      3.25      3.25      0.00      0.00      0.00      0.0012: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 1Linux 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/s12:17:20 AM      1.00      0.00  10233.00  18846.0012:17:19 AM  atmptf/s  estres/s retrans/s isegerr/s   orsts/s12:17:20 AM      0.00      0.00      0.00      0.00      0.0012:17:20 AM  active/s passive/s    iseg/s    oseg/s12:17:21 AM      1.00      0.00   8359.00   6039.0012:17:20 AM  atmptf/s  estres/s retrans/s isegerr/s   orsts/s12: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.92Tasks: 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)多個方面。

轉自:http://segmentfault.com/a/1190000004104493

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章