天天看點

Linux 系統監控、診斷工具之 IO waitLinux 系統監控、診斷工具之 IO wait

最近在做日志的實時同步,上線之前是做過單份線上日志壓力測試的,消息隊列和用戶端、本機都沒問題,但是沒想到上了第二份日志之後,問題來了:

叢集中的某台機器 top 看到負載巨高,叢集中的機器硬體配置一樣,部署的軟體都一樣,卻單單這一台負載有問題,初步猜測可能硬體有問題了。

同時,我們還需要把負載有異常的罪魁禍首揪出來,到時候從軟體、硬體層面分别尋找解決方案。

Linux 系統監控、診斷工具之 IO waitLinux 系統監控、診斷工具之 IO wait

<a target="_blank"></a>

從 top 中可以看到 load average 偏高,%wa 很高,%us 偏低:

Linux 系統監控、診斷工具之 IO waitLinux 系統監控、診斷工具之 IO wait

從上圖我們大緻可以推斷 io 遇到了瓶頸,下面我們可以再用相關的 io 診斷工具,具體的驗證排查下。

常用組合方式有如下幾種:

用vmstat、sar、iostat檢測是否是cpu瓶頸

用free、vmstat檢測是否是記憶體瓶頸

用iostat、dmesg 檢測是否是磁盤i/o瓶頸

用netstat檢測是否是網絡帶寬瓶頸

vmstat指令的含義為顯示虛拟記憶體狀态(“virtual memor statics”),但是它可以報告關于程序、記憶體、i/o等系統整體運作狀态。

Linux 系統監控、診斷工具之 IO waitLinux 系統監控、診斷工具之 IO wait

它的相關字段說明如下:

procs(程序)

r: 運作隊列中程序數量,這個值也可以判斷是否需要增加cpu。(長期大于1)

b: 等待io的程序數量,也就是處在非中斷睡眠狀态的程序數,展示了正在執行和等待cpu資源的任務個數。當這個值超過了cpu數目,就會出現cpu瓶頸了

memory(記憶體)

swpd: 使用虛拟記憶體大小,如果swpd的值不為0,但是si,so的值長期為0,這種情況不會影響系統性能。

free: 空閑實體記憶體大小。

buff: 用作緩沖的記憶體大小。

cache: 用作緩存的記憶體大小,如果cache的值大的時候,說明cache處的檔案數多,如果頻繁通路到的檔案都能被cache處,那麼磁盤的讀io bi會非常小。

swap(交換區)

si: 每秒從交換區寫到記憶體的大小,由磁盤調入記憶體。

so: 每秒寫入交換區的記憶體大小,由記憶體調入磁盤。

注意:記憶體夠用的時候,這2個值都是0,如果這2個值長期大于0時,系統性能會受到影響,磁盤io和cpu資源都會被消耗。有些朋友看到空閑記憶體(free)很少的或接近于0時,就認為記憶體不夠用了,不能光看這一點,還要結合si和so,如果free很少,但是si和so也很少(大多時候是0),那麼不用擔心,系統性能這時不會受到影響的。

io(輸入輸出)

(現在的linux版本塊的大小為1kb)

bi: 每秒讀取的塊數

bo: 每秒寫入的塊數

注意:随機磁盤讀寫的時候,這2個值越大(如超出1024k),能看到cpu在io等待的值也會越大。

system(系統)

in: 每秒中斷數,包括時鐘中斷。

cs: 每秒上下文切換數。

注意:上面2個值越大,會看到由核心消耗的cpu時間會越大。

cpu

(以百分比表示)

us: 使用者程序執行時間百分比(user time)。us的值比較高時,說明使用者程序消耗的cpu時間多,但是如果長期超50%的使用,那麼我們就該考慮優化程式算法或者進行加速。

sy: 核心系統程序執行時間百分比(system time)。sy的值高時,說明系統核心消耗的cpu資源多,這并不是良性表現,我們應該檢查原因。

wa: io等待時間百分比。wa的值高時,說明io等待比較嚴重,這可能由于磁盤大量作随機通路造成,也有可能磁盤出現瓶頸(塊操作)。

id: 空閑時間百分比

從 vmstat 中可以看到,cpu大部分的時間浪費在等待io上面,可能是由于大量的磁盤随機通路或者磁盤的帶寬所造成的,bi、bo 也都超過 1024k,應該是遇到了io瓶頸。

下面再用更加專業的磁盤 io 診斷工具來看下相關統計資料。

Linux 系統監控、診斷工具之 IO waitLinux 系統監控、診斷工具之 IO wait

rrqm/s: 每秒進行 merge 的讀操作數目。即 delta(rmerge)/s

wrqm/s: 每秒進行 merge 的寫操作數目。即 delta(wmerge)/s

r/s: 每秒完成的讀 i/o 裝置次數。即 delta(rio)/s

w/s: 每秒完成的寫 i/o 裝置次數。即 delta(wio)/s

rsec/s: 每秒讀扇區數。即 delta(rsect)/s

wsec/s: 每秒寫扇區數。即 delta(wsect)/s

rkb/s: 每秒讀k位元組數。是 rsect/s 的一半,因為每扇區大小為512位元組。(需要計算)

wkb/s: 每秒寫k位元組數。是 wsect/s 的一半。(需要計算)

avgrq-sz: 平均每次裝置i/o操作的資料大小 (扇區)。delta(rsect+wsect)/delta(rio+wio)

avgqu-sz: 平均i/o隊列長度。即 delta(aveq)/s/1000 (因為aveq的機關為毫秒)。

await: 平均每次裝置i/o操作的等待時間 (毫秒)。即 delta(ruse+wuse)/delta(rio+wio)

svctm: 平均每次裝置i/o操作的服務時間 (毫秒)。即 delta(use)/delta(rio+wio)

%util: 一秒中有百分之多少的時間用于 i/o 操作,或者說一秒中有多少時間 i/o 隊列是非空的。即 delta(use)/s/1000 (因為use的機關為毫秒)

可以看到兩塊硬碟中的 sdb 的使用率已經 100%,存在嚴重的 io 瓶頸,下一步我們就是要找出哪個程序在往這塊硬碟讀寫資料。

Linux 系統監控、診斷工具之 IO waitLinux 系統監控、診斷工具之 IO wait

根據 iotop 的結果,我們迅速的定位到是 flume 程序的問題,造成了大量的 io wait。

但是在開頭我已經說了,叢集中的機器配置一樣,部署的程式也都 rsync 過去的一模一樣,難道是硬碟壞了?

這得找運維同學來查證了,最後的結論是:

sdb為雙盤raid1,使用raid卡為“lsi logic / symbios logic sas1068e”,無cache。近400的iops壓力已經達到了硬體極限。而其它機器使用的raid卡是“lsi logic / symbios logic megaraid sas 1078”,有256mb cache,并未達到硬體瓶頸,解決辦法是更換能提供更大iops的機器,比如最後我們換了一台帶 perc6/i 內建raid控制器卡的機器。需要說明的是,raid資訊是在raid卡和磁盤固件裡面各存一份,磁盤上的raid資訊和raid卡上面的資訊格式要是比對的,否則raid卡識别不了就需要格式化磁盤。

iops本質上取決于磁盤本身,但是又很多提升iops的方法,加硬體cache、采用raid陣列是常用的辦法。如果是db那種iops很高的場景,現在流行用ssd來取代傳統的機械硬碟。

不過前面也說了,我們從軟硬體兩方面着手的目的就是看能否分别尋求代價最小的解決方案:

知道硬體的原因了,我們可以嘗試把讀寫操作移到另一塊盤,然後再看看效果: 

Linux 系統監控、診斷工具之 IO waitLinux 系統監控、診斷工具之 IO wait

其實,除了用上述專業的工具定位這個問題外,我們可以直接利用程序狀态來找到相關的程序。

我們知道程序有如下幾種狀态:

d uninterruptible sleep (usually io)

r running or runnable (on run queue)

s interruptible sleep (waiting for an event to complete)

t stopped, either by a job control signal or because it is being traced.

w paging (not valid since the 2.6.xx kernel)

x dead (should never be seen)

z defunct ("zombie") process, terminated but not reaped by its parent.

其中狀态為 d 的一般就是由于 wait io 而造成所謂的”非中斷睡眠“,我們可以從這點入手然後一步步的定位問題:

# for x in `seq 10`; do ps -eo state,pid,cmd | grep "^d"; echo "----"; sleep 5; done

d 248 [jbd2/dm-0-8]

d 16528 bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp

----

d 22 [kdmflush]

# 或者:

# while true; do date; ps auxf | awk '{if($8=="d") print $0;}'; sleep 1; done

tue aug 23 20:03:54 clt 2011

root 302 0.0 0.0 0 0 ? d may22 2:58 \_ [kdmflush]

root 321 0.0 0.0 0 0 ? d may22 4:11 \_ [jbd2/dm-0-8]

tue aug 23 20:03:55 clt 2011

tue aug 23 20:03:56 clt 2011

# cat /proc/16528/io

rchar: 48752567

wchar: 549961789

syscr: 5967

syscw: 67138

read_bytes: 49020928

write_bytes: 549961728

cancelled_write_bytes: 0

# lsof -p 16528

command pid user fd type device size/off node name

bonnie++ 16528 root cwd dir 252,0 4096 130597 /tmp

&lt;truncated&gt;

bonnie++ 16528 root 8u reg 252,0 501219328 131869 /tmp/bonnie.16528

bonnie++ 16528 root 9u reg 252,0 501219328 131869 /tmp/bonnie.16528

bonnie++ 16528 root 10u reg 252,0 501219328 131869 /tmp/bonnie.16528

bonnie++ 16528 root 11u reg 252,0 501219328 131869 /tmp/bonnie.16528

bonnie++ 16528 root 12u reg 252,0 501219328 131869 &lt;strong&gt;/tmp/bonnie.16528&lt;/strong&gt;

# df /tmp

filesystem 1k-blocks used available use% mounted on

/dev/mapper/workstation-root 7667140 2628608 4653920 37% /

# fuser -vm /tmp

user pid access command

/tmp: db2fenc1 1067 ....m db2fmp

db2fenc1 1071 ....m db2fmp

db2fenc1 2560 ....m db2fmp

db2fenc1 5221 ....m db2fmp

原文釋出時間:2014-12-16

本文來自雲栖合作夥伴“linux中國”

繼續閱讀