如何在一分鐘內對Linux服務器進行最佳性能診斷
2016-02-20 19:34:22 來源: 佚名 開源中國 評論:0 點擊:
當你為了解決一個性能問題登錄到一臺 Linux 服務器:在第一分鐘,你應該檢查些什么?
在 Netflix,我們有一個巨大的 EC2 Linux 云,以及大量的性能分析工具來監控和診斷其性能,其中包括用于云監控的 Atlas,以及用于按需實例分析的 Vector。雖然這些工具可以幫助我們解決大多數問題,但我們有時仍需要登錄到一個服務器實例,并運行一些標準 Linux 性能工具。
在這篇文章中,Netflix Performance Engineering 團隊將會向你講解在命令行中進行一次最佳的性能分析,需要在前 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 軟件包。這些命令展示出來的信息能夠幫你實施 USE 方法(一種用于定位性能瓶頸的方法),比如檢查各種資源(如 CPU、內存、磁盤等)的使用率、飽和度和錯誤信息。另外,在定位問題的過程中,你可以通過使用這些命令來排除某些導致問題的可能性,幫助你縮小檢查范圍,為下一步檢查指明方向。
下面的章節將以在一個生產環境上執行這些命令作為例子,簡單介紹這些命令。若想詳細了解這些工具的使用方法,請參考它們的 man 文檔。
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 分鐘對應的值遠小于 15 分鐘的值,那么可能說明這個問題已經過去了,你沒能及時觀察到。
在上面這個例子中,系統負載在隨著時間增加,因為最近一分鐘的負載值超過了 30,而 15 分鐘的平均負載則只有 19。這樣顯著的差距包含了很多含義,比方 CPU 負載。若要進一步確認的話,則要運行 vmstat 或 mpstat 命令,這兩個命令請參考后面的第 3 和第 4 章節。
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 條系統消息,如果它們存在的話。查找能夠導致性能問題的錯誤。上面的例子包含了 oom-killer,以及 TCP 丟棄一個請求。
千萬不要錯過這一步!dmesg 命令,永遠值得一試。
3.vmstat 1
- $ vmstat 1procs ---------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) 是虛擬內存統計的簡稱,其是一個常用工具(幾十年前為了 BSD 所創建)。其在每行打印一條關鍵的服務器的統計摘要。
vmstat 命令指定一個參數 1 運行,來打印每一秒的統計摘要。(這個版本的 vmstat)輸出的第一行的那些列,顯示的是開機以來的平均值,而不是前一秒的值。現在,我們跳過第一行,除非你想要了解并記住每一列。
檢查這些列:
◆ r:CPU 中正在運行和等待運行的進程數量。其提供了一個比平均負載更好的信號來確定 CPU 是否飽和,因為其不包含 I/O。解釋:“r”的值大于了 CPU 的數量就表示已經飽和了。
◆ free:以 kb 為單位顯示的空閑內存。如果數字位數很多,說明你有足夠的空閑內存。“free -m” 命令,是下面的第七個命令,其可以更好的說明空閑內存的狀態。
◆ si, so:Swap-ins 和 swap-outs。如果它們不是零,則代表你的內存不足了。
◆ us, sy, id, wa, st:這些都是平均了所有 CPU 的 CPU 分解時間。它們分別是用戶時間(user)、系統時間(內核)(system)、空閑(idle)、等待 I/O(wait)、以及占用時間(stolen)(被其他訪客,或使用 Xen,訪客自己獨立的驅動域)。
CPU 分解時間將會通過用戶時間加系統時間確認 CPU 是否為忙碌狀態。等待 I/O 的時間一直不變則表明了一個磁盤瓶頸;這就是 CPU 的閑置,因為任務都阻塞在等待掛起磁盤 I/O 上了。你可以把等待 I/O 當成是 CPU 閑置的另一種形式,其給出了為什么 CPU 閑置的一個線索。
對于 I/O 處理來說,系統時間是很重要的。一個高于 20% 的平均系統時間,可以值得進一步的探討:也許內核在處理 I/O 時效率太低了。
在上面的例子中,CPU 時間幾乎完全花在了用戶級,表明應用程序占用了太多 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 %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 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 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 的刷屏。其可用于實時查看,同時也可將你所看到的東西(復制粘貼)到你的調查記錄中。
上面的例子表明兩個 Java 進程正在消耗 CPU。%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.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 平均消耗時間。這是應用程序消耗的實際時間,因為它包括了排隊時間和處理時間。比預期更大的平均時間可能意味著設備的飽和或者設備出了問題。
◆ avgqu-sz:向設備發出請求的平均數量。值大于 1 說明已經飽和了(雖說設備可以并行處理請求,尤其是由多個磁盤組成的虛擬設備。)
◆ %util:設備利用率。這個值是一個顯示出該設備在工作時每秒處于忙碌狀態的百分比。若值大于 60%,通常表明性能不佳(可以從 await 中看出),雖然它取決于設備本身。值接近 100% 通常意味著已飽和。
如果該存儲設備是一個面向很多后端磁盤的邏輯磁盤設備,則 100% 利用率可能只是意味著當前正在處理某些 I/O 占用。然而,后端磁盤可能遠未飽和,并且可能能夠處理更多的工作。
請記住,磁盤 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:用于塊設備 I/O 的緩沖區緩存。
◆ cached:用于文件系統的頁面緩存。
我們只是想要檢查這些不接近零的大小,其可能會導致更高磁盤 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 %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 工具計量這個值。一如 nicstat,sar 顯示的這個值是很難精確取得的,在這個例子里面,它就沒在正常的工作(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/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 次數。
active 和 passive 的連接數往往對于描述一個粗略衡量服務器負載是非常有用的:新接受的連接數(passive),下行連接數(active)。可以理解為 active 連接是對外的,而 passive 連接是對內的,雖然嚴格來說并不完全正確(例如一個 localhost 到 localhost 的連接)。
重傳是出現一個網絡和服務器問題的一個征兆。其可能是由于一個不可靠的網絡(例如公網)造成的,或許也有可能是由于服務器過載并丟包。上面的例子顯示了每秒只有一個新的 TCP 連接。
10.top
- $ toptop - 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 的一個缺點是,很難看到數據隨時間變動的趨勢。vmstat 和 pidstat 提供的滾動輸出會更清楚一些。如果你不以足夠快的速度暫停輸出(Ctrl-S 暫停,Ctrl-Q 繼續),一些間歇性問題的線索也可能由于被清屏而丟失。
【編輯推薦】
上一篇:增量部署還是全量部署,你該如何選擇?
下一篇:技術專題:智能化運維
