最詳細的 Linux 伺服器效能引數指標

taozj發表於2017-01-09

一個基於Linux作業系統的伺服器執行的同時,也會表徵出各種各樣引數資訊。通常來說運維人員、系統管理員會對這些資料會極為敏感,但是這些引數對於開發者來說也十分重要,尤其當你的程式非正常工作的時候,這些蛛絲馬跡往往會幫助快速定位跟蹤問題。

這裡只是一些簡單的工具檢視系統的相關引數,當然很多工具也是通過分析加工/proc、/sys下的資料來工作的,而那些更加細緻、專業的效能監測和調優,可能還需要更加專業的工具(perf、systemtap等)和技術才能完成哦。畢竟來說,系統效能監控本身就是個大學問。

一、CPU和記憶體類

1.1 top

➜ ~ top

第一行後面的三個值是系統在之前1、5、15的平均負載,也可以看出系統負載是上升、平穩、下降的趨勢,當這個值超過CPU可執行單元的數目,則表示CPU的效能已經飽和成為瓶頸了。

第二行統計了系統的任務狀態資訊。running很自然不必多說,包括正在CPU上執行的和將要被排程執行的;sleeping通常是等待事件(比如IO操作)完成的任務,細分可以包括interruptible和uninterruptible的型別;stopped是一些被暫停的任務,通常傳送SIGSTOP或者對一個前臺任務操作Ctrl-Z可以將其暫停;zombie殭屍任務,雖然程式終止資源會被自動回收,但是含有退出任務的task descriptor需要父程式訪問後才能釋放,這種程式顯示為defunct狀態,無論是因為父程式提前退出還是未wait呼叫,出現這種程式都應該格外注意程式是否設計有誤。

第三行CPU佔用率根據型別有以下幾種情況:

  • (us) user: CPU在低nice值(高優先順序)使用者態所佔用的時間(nice<=0)。正常情況下只要伺服器不是很閒,那麼大部分的CPU時間應該都在此執行這類程式
  • (sy) system: CPU處於核心態所佔用的時間,作業系統通過系統呼叫(system call)從使用者態陷入核心態,以執行特定的服務;通常情況下該值會比較小,但是當伺服器執行的IO比較密集的時候,該值會比較大
  • (ni) nice: CPU在高nice值(低優先順序)使用者態以低優先順序執行佔用的時間(nice>0)。預設新啟動的程式nice=0,是不會計入這裡的,除非手動通過renice或者setpriority()的方式修改程式的nice值
  • (id) idle: CPU在空閒狀態(執行kernel idle handler)所佔用的時間
  • (wa) iowait: 等待IO完成做佔用的時間
  • (hi) irq: 系統處理硬體中斷所消耗的時間
  • (si) softirq: 系統處理軟中斷所消耗的時間,記住軟中斷分為softirqs、tasklets(其實是前者的特例)、work queues,不知道這裡是統計的是哪些的時間,畢竟work queues的執行已經不是中斷上下文了
  • (st) steal: 在虛擬機器情況下才有意義,因為虛擬機器下CPU也是共享物理CPU的,所以這段時間表明虛擬機器等待hypervisor排程CPU的時間,也意味著這段時間hypervisor將CPU排程給別的CPU執行,這個時段的CPU資源被”stolen”了。這個值在我KVM的VPS機器上是不為0的,但也只有0.1這個數量級,是不是可以用來判斷VPS超售的情況?

CPU佔用率高很多情況下意味著一些東西,這也給伺服器CPU使用率過高情況下指明瞭相應地排查思路:

  • (a) 當user佔用率過高的時候,通常是某些個別的程式佔用了大量的CPU,這時候很容易通過top找到該程式;此時如果懷疑程式異常,可以通過perf等思路找出熱點呼叫函式來進一步排查;
  • (b) 當system佔用率過高的時候,如果IO操作(包括終端IO)比較多,可能會造成這部分的CPU佔用率高,比如在file server、database server等型別的伺服器上,否則(比如>20%)很可能有些部分的核心、驅動模組有問題;
  • (c) 當nice佔用率過高的時候,通常是有意行為,當程式的發起者知道某些程式佔用較高的CPU,會設定其nice值確保不會淹沒其他程式對CPU的使用請求;
  • (d) 當iowait佔用率過高的時候,通常意味著某些程式的IO操作效率很低,或者IO對應裝置的效能很低以至於讀寫操作需要很長的時間來完成;
  • (e) 當irq/softirq佔用率過高的時候,很可能某些外設出現問題,導致產生大量的irq請求,這時候通過檢查/proc/interrupts檔案來深究問題所在;
  • (f) 當steal佔用率過高的時候,黑心廠商虛擬機器超售了吧!

第四行和第五行是實體記憶體和虛擬記憶體(交換分割槽)的資訊:

total = free + used + buff/cache,現在buffers和cached Mem資訊總和到一起了,但是buffers和cached Mem的關係很多地方都沒說清楚。其實通過對比資料,這兩個值就是/proc/meminfo中的Buffers和Cached欄位:Buffers是針對raw disk的塊快取,主要是以raw block的方式快取檔案系統的後設資料(比如超級塊資訊等),這個值一般比較小(20M左右);而Cached是針對於某些具體的檔案進行讀快取,以增加檔案的訪問效率而使用的,可以說是用於檔案系統中檔案快取使用。

而avail Mem是一個新的引數值,用於指示在不進行交換的情況下,可以給新開啟的程式多少記憶體空間,大致和free + buff/cached相當,而這也印證了上面的說法,free + buffers + cached Mem才是真正可用的實體記憶體。並且,使用交換分割槽不見得是壞事情,所以交換分割槽使用率不是什麼嚴重的引數,但是頻繁的swap in/out就不是好事情了,這種情況需要注意,通常表示實體記憶體緊缺的情況。

最後是每個程式的資源佔用列表,其中CPU的使用率是所有CPU core佔用率的總和。通常執行top的時候,本身該程式會大量的讀取/proc操作,所以基本該top程式本身也會是名列前茅的。

top雖然非常強大,但是通常用於控制檯實時監測系統資訊,不適合長時間(幾天、幾個月)監測系統的負載資訊,同時對於短命的程式也會遺漏無法給出統計資訊。

1.2 vmstat

vmstat是除top之外另一個常用的系統檢測工具,下面截圖是我用-j4編譯boost的系統負載。

r表示可執行程式數目,資料大致相符;而b表示的是uninterruptible睡眠的程式數目;swpd表示使用到的虛擬記憶體數量,跟top-Swap-used的數值是一個含義,而如手冊所說,通常情況下buffers數目要比cached Mem小的多,buffers一般20M這麼個數量級;io域的bi、bo表明每秒鐘向磁碟接收和傳送的塊數目(blocks/s);system域的in表明每秒鐘的系統中斷數(包括時鐘中斷),cs表明因為程式切換導致上下文切換的數目。

說到這裡,想到以前很多人糾結編譯linux kernel的時候-j引數究竟是CPU Core還是CPU Core+1?通過上面修改-j引數值編譯boost和linux kernel的同時開啟vmstat監控,發現兩種情況下context switch基本沒有變化,且也只有顯著增加-j值後context switch才會有顯著的增加,看來不必過於糾結這個引數了,雖然具體編譯時間長度我還沒有測試。資料說如果不是在系統啟動或者benchmark的狀態,引數context switch>100000程式肯定有問題。

1.3 pidstat

如果想對某個程式進行全面具體的追蹤,沒有什麼比pidstat更合適的了——棧空間、缺頁情況、主被動切換等資訊盡收眼底。這個命令最有用的引數是-t,可以將程式中各個執行緒的詳細資訊羅列出來。

-r: 顯示缺頁錯誤和記憶體使用狀況,缺頁錯誤是程式需要訪問對映在虛擬記憶體空間中但是還尚未被載入到實體記憶體中的一個分頁,缺頁錯誤兩個主要型別是

(a). minflt/s 指的minor faults,當需要訪問的物理頁面因為某些原因(比如共享頁面、快取機制等)已經存在於實體記憶體中了,只是在當前程式的頁表中沒有引用,MMU只需要設定對應的entry就可以了,這個代價是相當小的

(b). majflt/s 指的major faults,MMU需要在當前可用實體記憶體中申請一塊空閒的物理頁面(如果沒有可用的空閒頁面,則需要將別的物理頁面切換到交換空間去以釋放得到空閒物理頁面),然後從外部載入資料到該物理頁面中,並設定好對應的entry,這個代價是相當高的,和前者有幾個資料級的差異

-s:棧使用狀況,包括StkSize為執行緒保留的棧空間,以及StkRef實際使用的棧空間。使用ulimit -s發現CentOS 6.x上面預設棧空間是10240K,而CentOS 7.x、Ubuntu系列預設棧空間大小為8196K

-u:CPU使用率情況,引數同前面類似

-w:執行緒上下文切換的數目,還細分為cswch/s因為等待資源等因素導致的主動切換,以及nvcswch/s執行緒CPU時間導致的被動切換的統計

如果每次都先ps得到程式的pid後再操作pidstat會顯得很麻煩,所以這個殺手鐗的-C可以指定某個字串,然後Command中如果包含這個字串,那麼該程式的資訊就會被列印統計出來,-l可以顯示完整的程式名和引數
➜ ~ pidstat -w -t -C “ailaw” -l 

這麼看來,如果檢視單個尤其是多執行緒的任務時候,pidstat比常用的ps更好使!

1.4 其他

當需要單獨監測單個CPU情況的時候,除了htop還可以使用mpstat,檢視在SMP處理器上各個Core的工作量是否負載均衡,是否有某些熱點執行緒佔用Core。

➜ ~ mpstat -P ALL 1

如果想直接監測某個程式佔用的資源,既可以使用top -u taozj的方式過濾掉其他使用者無關程式,也可以採用下面的方式進行選擇,ps命令可以自定義需要列印的條目資訊:

while :; do ps -eo user,pid,ni,pri,pcpu,psr,comm | grep 'ailawd'; sleep 1; done

如想理清繼承關係,下面一個常用的引數可以用於顯示程式樹結構,顯示效果比pstree詳細美觀的多

➜ ~ ps axjf

二、磁碟IO類

iotop可以直觀的顯示各個程式、執行緒的磁碟讀取實時速率;lsof不僅可以顯示普通檔案的開啟資訊(使用者),還可以操作/dev/sda1這類裝置檔案的開啟資訊,那麼比如當分割槽無法umount的時候,就可以通過lsof找出磁碟該分割槽的使用狀態了,而且新增+fg引數還可以額外顯示檔案開啟flag標記。

2.1 iostat

➜ ~ iostat -xz 1

其實無論使用iostat -xz 1還是使用sar -d 1,對於磁碟重要的引數是:

avgqu-sz: 傳送給裝置I/O請求的等待佇列平均長度,對於單個磁碟如果值>1表明裝置飽和,對於多個磁碟陣列的邏輯磁碟情況除外;
await(r_await、w_await): 平均每次裝置I/O請求操作的等待時間(ms),包含請求排列在佇列中和被服務的時間之和;

svctm: 傳送給裝置I/O請求的平均服務時間(ms),如果svctm與await很接近,表示幾乎沒有I/O等待,磁碟效能很好,否則磁碟佇列等待時間較長,磁碟響應較差;

%util: 裝置的使用率,表明每秒中用於I/O工作時間的佔比,單個磁碟當%util>60%的時候效能就會下降(體現在await也會增加),當接近100%時候就裝置飽和了,但對於有多個磁碟陣列的邏輯磁碟情況除外;

還有,雖然監測到的磁碟效能比較差,但是不一定會對應用程式的響應造成影響,核心通常使用I/O asynchronously技術,使用讀寫快取技術來改善效能,不過這又跟上面的實體記憶體的限制相制約了。

上面的這些引數,對網路檔案系統也是受用的。

三、網路類

網路效能對於伺服器的重要性不言而喻,工具iptraf可以直觀的現實網路卡的收發速度資訊,比較的簡潔方便通過sar -n DEV 1也可以得到類似的吞吐量資訊,而網路卡都標配了最大速率資訊,比如百兆網路卡千兆網路卡,很容易檢視裝置的利用率。

通常,網路卡的傳輸速率並不是網路開發中最為關切的,而是針對特定的UDP、TCP連線的丟包率、重傳率,以及網路延時等資訊。

3.1 netstat

➜ ~ netstat -s

顯示自從系統啟動以來,各個協議的總體資料資訊。雖然引數資訊比較豐富有用,但是累計值,除非兩次執行做差才能得出當前系統的網路狀態資訊,亦或者使用watch眼睛直觀其數值變化趨勢。所以netstat通常用來檢測埠和連線資訊的:

netstat –all(a) –numeric(n) –tcp(t) –udp(u) –timers(o) –listening(l) –program(p)

–timers可以取消域名反向查詢,加快顯示速度;比較常用的有

➜  ~ netstat -antp  #列出所有TCP的連線
➜  ~ netstat -nltp   #列出本地所有TCP偵聽套接字,不要加-a引數

3.2 sar

sar這個工具太強大了,什麼CPU、磁碟、頁面交換啥都管,這裡使用-n主要用來分析網路活動,雖然網路中它還給細分了NFS、IP、ICMP、SOCK等各種層次各種協議的資料資訊,我們只關心TCP和UDP。下面的命令除了顯示常規情況下段、資料包的收發情況,還包括
TCP

➜ ~ sudo sar -n TCP,ETCP 1 

active/s:本地發起的TCP連線,比如通過connect(),TCP的狀態從CLOSED -> SYN-SENT

passive/s:由遠端發起的TCP連線,比如通過accept(),TCP的狀態從LISTEN -> SYN-RCVD

retrans/s(tcpRetransSegs):每秒鐘TCP重傳數目,通常在網路質量差,或者伺服器過載後丟包的情況下,根據TCP的確認重傳機制會發生重傳操作

isegerr/s(tcpInErrs):每秒鐘接收到出錯的資料包(比如checksum失敗)

UDP

➜ ~ sudo sar -n UDP 1 

noport/s(udpNoPorts):每秒鐘接收到的但是卻沒有應用程式在指定目的埠的資料包個數

idgmerr/s(udpInErrors):除了上面原因之外的本機接收到但卻無法派發的資料包個數

當然,這些資料一定程度上可以說明網路可靠性,但也只有同具體的業務需求場景結合起來才具有意義。

3.3 tcpdump

tcpdump不得不說是個好東西。大家都知道本地除錯的時候喜歡使用wireshark,但是線上服務端出現問題怎麼弄呢?附錄的參考文獻給出了思路:復原環境,使用tcpdump進行抓包,當問題復現(比如日誌顯示或者某個狀態顯現)的時候,就可以結束抓包了,而且tcpdump本身帶有-C/-W引數,可以限制抓取包儲存檔案的大小,當達到這個這個限制的時候儲存的包資料自動rotate,所以抓包數量總體還是可控的。此後將資料包拿下線來,用wireshark想怎麼看就怎麼看,豈不樂哉!tcpdump雖然沒有GUI介面,但是抓包的功能絲毫不弱,可以指定網路卡、主機、埠、協議等各項過濾引數,抓下來的包完整又帶有時間戳,所以線上程式的資料包分析也可以這麼簡單。
下面就是一個小的測試,可見Chrome啟動時候自動向Webserver發起建立了三條連線,由於這裡限制了dst port引數,所以服務端的應答包被過濾掉了,拿下來用wireshark開啟,SYNC、ACK建立連線的過程還是很明顯的!在使用tcpdump的時候,需要儘可能的配置抓取的過濾條件,一方面便於接下來的分析,二則tcpdump開啟後對網路卡和系統的效能會有影響,進而會影響到線上業務的效能。

本文完!

相關文章