“如果你的Linux服務(wù)器突然負(fù)載暴增拴签,告警短信快發(fā)爆你的手機(jī),如何在最短時(shí)間內(nèi)找出Linux性能問(wèn)題所在典格?來(lái)看Netflix性能工程團(tuán)隊(duì)的這篇博文母怜,看它們通過(guò)十條命令在一分鐘內(nèi)對(duì)機(jī)器性能問(wèn)題進(jìn)行診斷。
概述
“通過(guò)執(zhí)行以下命令善榛,可以在1分鐘內(nèi)對(duì)系統(tǒng)資源使用情況有個(gè)大致的了解辩蛋。
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包,有一些由procps包提供移盆。這些命令的輸出堪澎,有助于快速定位性能瓶頸,檢查出所有資源(CPU味滞、內(nèi)存、磁盤IO等)的利用率(utilization)钮呀、飽和度(saturation)和錯(cuò)誤(error)度量剑鞍,也就是所謂的USE方法。
“下面我們來(lái)逐一介紹下這些命令爽醋,有關(guān)這些命令更多的參數(shù)和說(shuō)明蚁署,請(qǐng)參照命令的手冊(cè)。
uptime
$ uptime
23:51:26 up 21:31,? 1 user,? load average: 30.02, 26.43, 19.02
“這個(gè)命令可以快速查看機(jī)器的負(fù)載情況蚂四。在Linux系統(tǒng)中光戈,這些數(shù)據(jù)表示等待CPU資源的進(jìn)程和阻塞在不可中斷IO進(jìn)程(進(jìn)程狀態(tài)為D)的數(shù)量。這些數(shù)據(jù)可以讓我們對(duì)系統(tǒng)資源使用有一個(gè)宏觀的了解遂赠。
“命令的輸出分別表示1分鐘久妆、5分鐘、15分鐘的平均負(fù)載情況跷睦。通過(guò)這三個(gè)數(shù)據(jù)筷弦,可以了解服務(wù)器負(fù)載是在趨于緊張還是區(qū)域緩解。如果1分鐘平均負(fù)載很高抑诸,而15分鐘平均負(fù)載很低烂琴,說(shuō)明服務(wù)器正在命令高負(fù)載情況,需要進(jìn)一步排查CPU資源都消耗在了哪里蜕乡。反之奸绷,如果15分鐘平均負(fù)載很高,1分鐘平均負(fù)載較低层玲,則有可能是CPU資源緊張時(shí)刻已經(jīng)過(guò)去号醉。
“上面例子中的輸出反症,可以看見最近1分鐘的平均負(fù)載非常高,且遠(yuǎn)高于最近15分鐘負(fù)載扣癣,因此我們需要繼續(xù)排查當(dāng)前系統(tǒng)中有什么進(jìn)程消耗了大量的資源惰帽。可以通過(guò)下文將會(huì)介紹的vmstat父虑、mpstat等命令進(jìn)一步排查该酗。
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.
“該命令會(huì)輸出系統(tǒng)日志的最后10行。示例中的輸出士嚎,可以看見一次內(nèi)核的oom kill和一次TCP丟包呜魄。這些日志可以幫助排查性能問(wèn)題。千萬(wàn)不要忘了這一步莱衩。
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(8) 命令爵嗅,每行會(huì)輸出一些系統(tǒng)核心指標(biāo),這些指標(biāo)可以讓我們更詳細(xì)的了解系統(tǒng)狀態(tài)笨蚁。后面跟的參數(shù)1睹晒,表示每秒輸出一次統(tǒng)計(jì)信息,表頭提示了每一列的含義括细,這幾介紹一些和性能調(diào)優(yōu)相關(guān)的列:
r:等待在CPU資源的進(jìn)程數(shù)伪很。這個(gè)數(shù)據(jù)比平均負(fù)載更加能夠體現(xiàn)CPU負(fù)載情況,數(shù)據(jù)中不包含等待IO的進(jìn)程奋单。如果這個(gè)數(shù)值大于機(jī)器CPU核數(shù)锉试,那么機(jī)器的CPU資源已經(jīng)飽和。
free:系統(tǒng)可用內(nèi)存數(shù)(以千字節(jié)為單位)览濒,如果剩余內(nèi)存不足呆盖,也會(huì)導(dǎo)致系統(tǒng)性能問(wèn)題。下文介紹到的free命令贷笛,可以更詳細(xì)的了解系統(tǒng)內(nèi)存的使用情況应又。
si, so:交換區(qū)寫入和讀取的數(shù)量。如果這個(gè)數(shù)據(jù)不為0昨忆,說(shuō)明系統(tǒng)已經(jīng)在使用交換區(qū)(swap)丁频,機(jī)器物理內(nèi)存已經(jīng)不足。
us, sy, id, wa, st:這些都代表了CPU時(shí)間的消耗邑贴,它們分別表示用戶時(shí)間(user)席里、系統(tǒng)(內(nèi)核)時(shí)間(sys)、空閑時(shí)間(idle)拢驾、IO等待時(shí)間(wait)和被偷走的時(shí)間(stolen奖磁,一般被其他虛擬機(jī)消耗)。
“上述這些CPU時(shí)間繁疤,可以讓我們很快了解CPU是否出于繁忙狀態(tài)咖为。一般情況下秕狰,如果用戶時(shí)間和系統(tǒng)時(shí)間相加非常大,CPU出于忙于執(zhí)行指令躁染。如果IO等待時(shí)間很長(zhǎng)鸣哀,那么系統(tǒng)的瓶頸可能在磁盤IO。
“示例命令的輸出可以看見吞彤,大量CPU時(shí)間消耗在用戶態(tài)我衬,也就是用戶應(yīng)用程序消耗了CPU時(shí)間。這不一定是性能問(wèn)題饰恕,需要結(jié)合r隊(duì)列挠羔,一起分析。
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
[...]
“該命令可以顯示每個(gè)CPU的占用情況埋嵌,如果有一個(gè)CPU占用率特別高破加,那么有可能是一個(gè)單線程應(yīng)用程序引起的。
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? java07: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
“pidstat命令輸出進(jìn)程的CPU占用率雹嗦,該命令會(huì)持續(xù)輸出范舀,并且不會(huì)覆蓋之前的數(shù)據(jù),可以方便觀察系統(tǒng)動(dòng)態(tài)了罪。如上的輸出尿背,可以看見兩個(gè)JAVA進(jìn)程占用了將近1600%的CPU時(shí)間,既消耗了大約16個(gè)CPU核心的運(yùn)算資源捶惜。
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
[...]
“iostat命令主要用于查看機(jī)器磁盤IO情況。該命令輸出的列荔烧,主要含義是:
r/s, w/s, rkB/s, wkB/s:分別表示每秒讀寫次數(shù)和每秒讀寫數(shù)據(jù)量(千字節(jié))吱七。讀寫量過(guò)大,可能會(huì)引起性能問(wèn)題鹤竭。
await:IO操作的平均等待時(shí)間踊餐,單位是毫秒。這是應(yīng)用程序在和磁盤交互時(shí)臀稚,需要消耗的時(shí)間吝岭,包括IO等待和實(shí)際操作的耗時(shí)。如果這個(gè)數(shù)值過(guò)大吧寺,可能是硬件設(shè)備遇到了瓶頸或者出現(xiàn)故障窜管。
avgqu-sz:向設(shè)備發(fā)出的請(qǐng)求平均數(shù)量。如果這個(gè)數(shù)值大于1稚机,可能是硬件設(shè)備已經(jīng)飽和(部分前端硬件設(shè)備支持并行寫入)幕帆。
%util:設(shè)備利用率。這個(gè)數(shù)值表示設(shè)備的繁忙程度赖条,經(jīng)驗(yàn)值是如果超過(guò)60失乾,可能會(huì)影響IO性能(可以參照IO操作平均等待時(shí)間)常熙。如果到達(dá)100%,說(shuō)明硬件設(shè)備已經(jīng)飽和碱茁。
“如果顯示的是邏輯設(shè)備的數(shù)據(jù)裸卫,那么設(shè)備利用率不代表后端實(shí)際的硬件設(shè)備已經(jīng)飽和。值得注意的是纽竣,即使IO性能不理想墓贿,也不一定意味這應(yīng)用程序性能會(huì)不好,可以利用諸如預(yù)讀取退个、寫緩存等策略提升應(yīng)用性能募壕。
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
“free命令可以查看系統(tǒng)內(nèi)存的使用情況,-m參數(shù)表示按照兆字節(jié)展示语盈。最后兩列分別表示用于IO緩存的內(nèi)存數(shù)舱馅,和用于文件系統(tǒng)頁(yè)緩存的內(nèi)存數(shù)。需要注意的是刀荒,第二行-/+ buffers/cache代嗤,看上去緩存占用了大量?jī)?nèi)存空間。這是Linux系統(tǒng)的內(nèi)存使用策略缠借,盡可能的利用內(nèi)存干毅,如果應(yīng)用程序需要內(nèi)存,這部分內(nèi)存會(huì)立即被回收并分配給應(yīng)用程序泼返。因此硝逢,這部分內(nèi)存一般也被當(dāng)成是可用內(nèi)存。
“如果可用內(nèi)存非常少绅喉,系統(tǒng)可能會(huì)動(dòng)用交換區(qū)(如果配置了的話)渠鸽,這樣會(huì)增加IO開銷(可以在iostat命令中提現(xiàn)),降低系統(tǒng)性能柴罐。
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
“sar命令在這里可以查看網(wǎng)絡(luò)設(shè)備的吞吐率徽缚。在排查性能問(wèn)題時(shí),可以通過(guò)網(wǎng)絡(luò)設(shè)備的吞吐量革屠,判斷網(wǎng)絡(luò)設(shè)備是否已經(jīng)飽和凿试。如示例輸出中,eth0網(wǎng)卡設(shè)備似芝,吞吐率大概在22 Mbytes/s那婉,既176 Mbits/sec,沒(méi)有達(dá)到1Gbit/sec的硬件上限党瓮。
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
“sar命令在這里用于查看TCP連接狀態(tài)吧恃,其中包括:
active/s:每秒本地發(fā)起的TCP連接數(shù),既通過(guò)connect調(diào)用創(chuàng)建的TCP連接麻诀;
passive/s:每秒遠(yuǎn)程發(fā)起的TCP連接數(shù)痕寓,即通過(guò)accept調(diào)用創(chuàng)建的TCP連接傲醉;
retrans/s:每秒TCP重傳數(shù)量;
“TCP連接數(shù)可以用來(lái)判斷性能問(wèn)題是否由于建立了過(guò)多的連接呻率,進(jìn)一步可以判斷是主動(dòng)發(fā)起的連接硬毕,還是被動(dòng)接受的連接。TCP重傳可能是因?yàn)榫W(wǎng)絡(luò)環(huán)境惡劣礼仗,或者服務(wù)器壓力過(guò)大導(dǎo)致丟包吐咳。
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命令包含了前面好幾個(gè)命令的檢查的內(nèi)容。比如系統(tǒng)負(fù)載情況(uptime)元践、系統(tǒng)內(nèi)存使用情況(free)韭脊、系統(tǒng)CPU使用情況(vmstat)等。因此通過(guò)這個(gè)命令单旁,可以相對(duì)全面的查看系統(tǒng)負(fù)載的來(lái)源沪羔。同時(shí),top命令支持排序象浑,可以按照不同的列排序蔫饰,方便查找出諸如內(nèi)存占用最多的進(jìn)程、CPU占用率最高的進(jìn)程等愉豺。
“但是篓吁,top命令相對(duì)于前面一些命令,輸出是一個(gè)瞬間值蚪拦,如果不持續(xù)盯著杖剪,可能會(huì)錯(cuò)過(guò)一些線索。這時(shí)可能需要暫停top命令刷新驰贷,來(lái)記錄和比對(duì)數(shù)據(jù)摘盆。
總結(jié)
“排查L(zhǎng)inux服務(wù)器性能問(wèn)題還有很多工具,上面介紹的一些命令饱苟,可以幫助我們快速的定位問(wèn)題。例如前面的示例輸出狼渊,多個(gè)證據(jù)證明有JAVA進(jìn)程占用了大量CPU資源箱熬,之后的性能調(diào)優(yōu)就可以針對(duì)應(yīng)用程序進(jìn)行。