Linux 性能診斷:快速檢查單(Netflix版)

快速檢查單

快速檢查單(Quick Reference Handbook,QRH)是飛行員在飛行過程中依賴的重要指導性文件。

第一張飛行檢查單起源于一次嚴重的航空事故。1935年波音公司研制的一架新型轟炸機在試飛過程中突然墜機,導致2名機組人員遇難——包括一名最優秀的試飛員普洛耶爾·希爾少校。后來的調查結果分析,事故并不是機械故障引起的,而是人為失誤造成。新型飛機比以往的飛機更復雜,飛行員要管理4臺發動機,操控起落架、襟翼、電動配平調整片和恒速液壓變距螺旋槳等。因為忙于各種操作,希爾少校忘記了一項簡單卻很重要的工作 —— 在起飛前忘記對新設計的升降舵和方向舵實施解鎖。

美國軍方組織飛行專家編制了一份飛行檢查單,將起飛、巡航、著陸和滑行各階段的重要步驟寫在一張索引卡片上。飛行員根據檢查單的提示檢查剎車是否松開,飛行儀表是否準確設定,機艙門窗是否完全關閉,升降舵等控制面是否已經解鎖。

Netflix 性能工程團隊

登陸一臺 Linux 服務器排查性能問題:開始一分鐘你該檢查哪些呢?
在 Netflix 我們有一個龐大的 EC2 Linux集群,也有許多性能分析工具用于監視和檢查它們的性能。它們包括用于云監測的Atlas (工具代號) ,用于實例分析的 Vector (工具代號) 。盡管這些工具能幫助我們解決大部分問題,我們有時也需要登陸一臺實例、運行一些標準的 Linux 性能分析工具。在這篇文章,Netflix 性能工程團隊將向您展示:在開始的60秒鐘,利用標準的Linux命令行工具,執行一次充分的性能檢查。

Linux 性能分析黃金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包。這些命令輸出的指標,將幫助你掌握一些有效的方法:一整套尋找性能瓶頸的方法論。這些命令需要檢查所有資源的利用率、飽和度和錯誤信息(CPU、內存、磁盤等)。同時,當你檢查或排除一些資源的時候,需要注意在檢查過程中,根據指標數據指引,逐步縮小目標范圍。

接下來的章節,將結合生產環境的案例演示這些命令。如果希望了解這些工具的詳細信息,可以查閱它們的操作文檔。

1. uptime

$ uptime
23:51:26up21:31, 1user, loadaverage:30.02,26.43,19.02

這是一個快速查看平均負載的方法,表示等待運行的任務(進程)數量。在Linux系統中,這些數字包含等待CPU運行的進程數,也包括不間斷I/O阻塞的進程數(通常是磁盤I/O)。它展示了一個資源負載(或需求)的整體概念,但是無法理解其中的內涵,在沒有其它工具的情況下。僅僅是一種快速查看手段而已。

這三個數字呈現出平均負載在幾何級減弱,依次表示持續1分鐘,5分鐘和15分鐘內。這三個數字能告訴我們負載在時間線上是如何變化的。舉例說明,如果你在一個問題服務器上執行檢查,1分鐘的值遠遠低于15分鐘的值,可以判斷出你也許登錄得太晚了,已經錯過了問題。

在上面的例子中,平均負載的數值顯示最近正在上升,1分鐘值高達30,對比15分鐘值則是19。這些指標值像現在這么大意味著很多情況:也許是CPU繁忙;vmstat 或者 mpstat 將可以確認,本系列的第三和第四條命令。

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-r
ss:0kB
[2320864.954447] TCP: Possible SYN flooding on port 7001. Dropping request. Check SNMP cou
nters.

這個結果輸出了最近10條系統信息??梢圆榭吹揭鹦阅軉栴}的錯誤。上面的例子包含了oom-killer,以及TCP丟包。

譯者注:除了error級的日志,info級的也要留個心眼,可能包含一些隱藏信息。

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

vmstat 是一個獲得虛擬內存狀態概況的通用工具(最早創建于10年前的BSD)。它每一行記錄了關鍵的服務器統計信息。vmstat 運行的時候有一個參數1,用于輸出一秒鐘的概要數據。第一行輸出顯示啟動之后的平均值,用以替代之前的一秒鐘數據?,F在,跳過第一行,讓我們來學習并且記住每一列代表的意義。

r:正在CPU上運行或等待運行的進程數。相對于平均負載來說,這提供了一個更好的、用于查明CPU飽和度的指標,它不包括I/O負載。注: “r”值大于CPU數即是飽和。

free: 空閑內存(kb)
如果這個數值很大,表明你還有足夠的內存空閑。包括命令7“free m”,很好地展現了空閑內存的狀態。

si, so: swap入/出。如果這個值非0,證明內存溢出了。

us, sy, id, wa, st:它們是CPU分類時間,針對所有CPU的平均訪問。分別是用戶時間,系統時間(內核),空閑,I/O等待時間,以及被偷走的時間(其它訪客,或者是Xen)。CPU分類時間將可以幫助確認,CPU是否繁忙,通過累計用戶系統時間。等待I/O的情形肯定指向的是磁盤瓶頸;這個時候CPU通常是空閑的,因為任務被阻塞以等待分配磁盤I/O。你可以將等待I/O當作另一種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,可以判斷是屬于單進程的應用程序。

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 有一點像頂級視圖-針對每一個進程,但是輸出的時候滾屏,而不是清屏。它非常有用,特別是跨時間段查看的模式,也能將你所看到的信息記錄下來,以利于進一步的研究。上面的例子識別出兩個 java 進程引起的CPU耗盡。“%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
[...]

這是一個理解塊設備(磁盤)極好的工具,不論是負載評估還是作為性能測試成績。

r/s, w/s, rkB/s, wkB/s: 這些是該設備每秒讀%、寫%、讀Kb、寫Kb??捎糜诿枋龉ぷ髫摵?。一個性能問題可能只是簡單地由于一個過量的負載引起。

await: I/O平均時間(毫秒)
這是應用程序需要的時間,它包括排隊以及運行的時間。
遠遠大于預期的平均時間可以作為設備飽和,或者設備問題的指標。

avgqu-sz: 向設備發出的平均請求數。
值大于1可視為飽和(盡管設備能對請求持續運行,特別是前端的虛擬設備-后端有多個磁盤)。

%util: 設備利用率
這是一個實時的繁忙的百分比,顯示設備每秒鐘正在進行的工作。值大于60%屬于典型的性能不足(可以從await處查看),盡管它取決于設備。值接近100% 通常指示飽和。如果存儲設備是一個前端邏輯磁盤、后掛一堆磁盤,那么100%的利用率也許意味著,一些已經處理的I/O此時占用100%,然而,后端的磁盤也許遠遠沒有達到飽和,其實可以承擔更多的工作。

切記:磁盤I/O性能低并不一定是應用程序問題。許多技術一貫使用異步I/O,所以應用程序并不會阻塞,以及遭受直接的延遲(例如提前加載,緩沖寫入)。

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: buffer cache,用于塊設備I/O。
cached:page cache, 用于文件系統。

我們只是想檢查這些指標值不為0——那樣意味著磁盤I/O高、性能差(確認需要用iostat)。上面的例子看起來不錯,每一類內存都有富余。

“-/+ buffers/cache”: 提供了關于內存利用率更加準確的數值。

Linux可以將空閑內存用于緩存,并且在應用程序需要的時候收回。所以應用到緩存的內存必須以另一種方式包括在內存空閑的數據里面。有一個網站linux ate my ram,專門探討這個困惑。它還有更令人困惑的地方,如果在Linux上使用ZFS,正如我們運行一些服務,ZFS擁有自己的文件系統緩存,也不能在free -m 的輸出里正確反映。這種情況會顯示系統空閑內存不足,但是內存實際上可用,通過回收 ZFS 的緩存。

關于 Linux 內存管理的更多內容,可以閱讀操作系統原理:How Linux Works (Memroy)。

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 收包大道 22 Mbytes/s, 即176 Mbits/sec (就是說,在 1 Gbit/sec 的限制之內)。此版本也有一個體現設備利用率的 “%ifutil” (兩個方向最大值),我們也可以使用 Brendan的nicstat 工具來度量。和 nicstat 類似,這個值很難準確獲取,看起來在這個例子中并沒有起作用(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 連接數 /每秒(例如,通過connect() )
passive/s: 遠程初始化的 TCP 連接數/每秒(例如,通過accept() )
retrans/s: TCP重發數/每秒

這些活躍和被動的計數器常常作為一種粗略的服務負載度量方式:新收到的連接數 (被動的),以及下行流量的連接數 (活躍的)。這也許能幫助我們理解,活躍的都是外向的,被動的都是內向的,但是嚴格來說這種說法是不準確的(例如,考慮到“本地-本地”的連接)。重發數是網絡或服務器問題的一個標志;它也許是因為不可靠的網絡(如,公共互聯網),也許是由于一臺服務器已經超負荷、發生丟包。
上面的例子顯示每秒鐘僅有一個新的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命令包含了許多我們之前已經檢查的指標。它可以非常方便地運行,看看是否任何東西看起來與從前面的命令的結果完全不同,可以表明負載指標是不斷變化的。頂部下面的輸出,很難按照時間推移的模式查看,可能使用如 vmstat 和 pidstat 等工具會更清晰,它們提供滾動輸出。如果你保持輸出的動作不夠快 (CtrlS 要暫停,CtrlQ 繼續),屏幕將清除,間歇性問題的證據也會丟失。

總結

故障檢查過程中,人的作用主要是作出決策。遺忘、遺漏、麻痹、松懈是每個人都會犯的錯誤,好的公司都會根據經驗編制檢查單,提高工作效率,降低人為失誤發生的概率。出于競爭因素考慮,應該充分重視檢查單的更新、完善、自動化,以此為基礎建立自己的技術壁壘。

擴展閱讀:Linux 操作系統

推薦:電子書《Linux Perf Master》

發表在GitBook平臺,歡迎訂閱、下載、批評指正: https://www.gitbook.com/book/riboseyim/linux-perf-master/details

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。