解決Linux性能問題的前60秒

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

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

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

最開始的60秒……

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

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))ios

接下來的章節裏咱們將結合實際例子講解這些命令。若是你想了解更多的相關信息,請查看它們的man page。git

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)上的進程。它展現了資源負載(或需求)的大體狀況,不過進一步的解讀還有待其它工具的協助。對它的具體數值不用太較真。github

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

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

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請求的公告。apache

不要漏了這一步!檢查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,可以更清楚地說明空閒內存的狀態。

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 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/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 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

若是你在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 00 S 0.00.02:38.05 rcu_sched 

top命令包括不少咱們以前檢查過的指標。它適合用來查看相比於以前的命令輸出的結果,負載有了哪些變更。

不能清晰顯示數據隨時間變更的狀況,這是top的一個缺點。相較而言,vmstatpidstat的輸出不會覆蓋掉以前的結果,所以更適合查看數據隨時間的變更狀況。另外,若是你不能及時暫停top的輸出(Ctrl-s暫停,Ctrl-q繼續),也許某些關鍵線索會湮滅在新的輸出中。

在這以後…

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

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

相關文章
相關標籤/搜索