linux後端診斷與調試技術,linux後端調試
本文不是liunx命令使用教程,也不打算全方面闡明其用法,互連網公司項目很多,服務程式之間相互依賴調用很複雜,各種因素會影響線程服務正常運行,特別是基礎服務元件更是如此,當出現各種問題時,如何診斷linux下哪個環節出現問題或狀況。從linux系統層面看,通過各種操作命令和手段快速定位線上程式的癥狀和要害很有必要。比如說:當線上服務長時間正常運行,張三某天突然監控到自己的程式出問題了,自己負責某個程式不提供服務或服務處於掛死(進程還在,但無法接收外部響應)狀態,查看應用程式記錄檔沒發現明顯錯誤或可提示資訊(看了隱藏比較深),可能(壓力比較大,時間緊迫)經驗豐富開發工程師也一時半會找不出癥狀所在,筆者想盡量覆蓋關鍵和重要部分分享給讀者,以期待提供有價值可參考的依據,筆者更想提供一些自己遇到問題的解決方案和思路作為大家的參考,但限於水平限制,難免有疏漏和不足之處,歡迎大家提出寶貴意見和想法以協助我更正或提高。
下面出現的問題是工程師日常開發中真實寫照。
診斷技術與調試解釋
筆者從上述6個方面擴充到多個維度剖析,應用程式或服務出現問題的癥狀所在,正因為互連網公司特殊性,技術工程師流動相對比較頻繁,崗位變更交接等原因,造成了後來接手人(新手)無法及時應對線上出現各種狀況。或因為經驗不足,或因為對線上情況不瞭解等,增加了很多不確定因素。如果我們有一套簡單通用可行檢測和衡量規則,就大大降低風險。希望能通過這個參考手冊的協助,分析大量線上參數資料並從中找到蛛絲馬跡,也能縮小排查有問題程式的範圍。
正因為程式出現問題需要診斷和調試,那需要通過分析和判斷哪些方面因素會引起linux效能波動。
孫子.謀攻
知己知彼,百戰不殆;
不知彼而知己,一勝一負;
不知彼,不知己,每戰必殆。
影響Linux效能因素
- 作業系統
- CPU
- 記憶體
- 磁碟I/O及效能
- 網路I/O狀況及效能
linux系統效能評估標準
注:關於swap和paging含義後面有名稱解釋
linux 系統效能分析命令或工具
常用命令:
dstat,vmstat、sar、iostat、netstat、free、ps、top等
效能分析和診斷工具
- 用vmstat、sar、iostat檢測是否是CPU、磁碟,記憶體瓶頸
- 用free、vmstat檢測是否是記憶體、IO瓶頸
- 用iostat檢測是否是磁碟I/O瓶頸
- 用dstat檢測是否是網路頻寬、磁碟io、記憶體、負載等綜合瓶頸分析
- 用mpstat檢測是否cpu調用不均衡,也可以使用top替代
- 用pidstat檢測相應進程cpu消耗情況
- 用netstat檢測socket buffer有未發送或處理的資料,從而判斷程式處理能力下降或出現問題.
- 用lsof檢測開啟檔案描述(網路檔案和磁碟檔案,管道等)符過多,導致資源不足
- 用df和du組合檢測掛載磁碟或目錄佔用空間巨大或inode節點消耗殆盡。
- 用iftop檢查2台主機間是否存在流量瓶頸.
下面命令中參數名詞解釋:
buffer是用於存放(緩衝)要輸出到disk(塊裝置)的資料的,
cache是存放從disk上讀出的資料。這buffer和cache是為了提高IO效能的,並由OS管理。
swap: linux核心讀寫虛擬記憶體是以 “頁” 為單位操作的,把記憶體轉移到硬碟交換空間(SWAP)和從交換空間讀取到記憶體 的時候都是按頁來讀寫的。
Paging:記憶體和SWAP的這種交換過程稱為頁面交換(Paging)
Linux - toptop
- shift + h 按線程查看cpu消耗情況
- 查看每個核消耗情況
- us 過高說明應用程式消耗了大部分cpu
- sy 過高表示系統線程切換頻繁
- wa 表示為在執行過程中等待io所佔的百分比 hi 硬體中斷(ex:網卡接收資料頻發)
- top -p pid 多列資訊列表中直顯示對應進程資訊.
Linux - freefree -m
-/+ buffers/cache
used應用程式總共使用的記憶體數=Mem.used-Mem.buffers-Mem.cached
應用程式還未使用的記憶體數=Mem.free+Mem.buffers+Mem.cached
上面是free -m的運行結果,一共有4行。為了方便說明,筆者加上了列號。這樣可以把free的輸出看成一個二維數組rowcols(Free Output),下面可以使用2個等式表示兩個等式
rowcols[3][2] = rowcols[2][2] - rowcols[2][5] - rowcols[2][6]
rowcols[3][3] = rowcols[2][3] + rowcols[2][5] + rowcols[2][6]
注:free命令中記憶體參數與top中第四行,五行--對應,top就是少了free第三行參數值
Linux - netstat / ssnetstat –an | grep 連接埠
Recv-Q 網路接收隊列 一般情況為0,如果持續為非0表示收到的資料已經在本地接收緩衝,應用程式還沒處理,可能是應用程式處理效能下降。
Send-Q 發送隊列 一般情況為0,如果持續為非0可能是應用向外發送資料包過快,或者是 對方接收資料包不夠快。
netstat –an | grep 連接埠 (查看應用程式連接埠是否正常監聽)
以前遇到過分布式緩衝memcached在高峰訪問中會出現這種現象,由於高峰時期極端情況下多線程lock記憶體池原因,導致服務端效能急劇下降。
Linux - vmstatvmstat 1 10
vmstat CPU使用率,記憶體使用量,虛擬記憶體交換情況,IO讀寫情況
一般使用格式為:vmstat interval count //表示輸出頻率1秒,連續輸出10次
使用執行個體: vmstat 1 10
如果CPU的sy和us值相加的百分比接近100%,或者運行隊列(r)中等待 的進程數總是不等於0,且經常大於4,同時id也經常小於40,則該系 統受限於CPU;如果bi、bo的值總是不等於0,則該系統受限於記憶體。 swpd值過高一般情況由於實體記憶體不夠用.
Linux - sarsar 1 10
格式如下:sar -d interval count
需要關注幾個參數:
- await表示平均每次裝置I/O操作的等待時間(以毫秒為單位)。
- svctm表示平均每次裝置I/O操作的服務時間(以毫秒為單位)。
- %util表示一秒中有百分之幾的時間用於I/O操作。
利用sar作效能評估磁碟IO效能,一般有如下評判標準:
- 正常情況下svctm應該是小於await值的,而svctm的大小和磁碟效能有關,CPU、記憶體的負荷也會對svctm值造成影響,過多的請求也會間接的導致svctm值的增加。await值的大小一般取決與svctm的值和I/O隊列長度以及I/O請求模式,如果svctm的值與await很接近,表示幾乎沒有I/O等待,磁碟效能很好,如果await的值遠高於svctm的值,則表示I/O隊列等待太長,系統上啟動並執行應用程式將變慢,此時可以通過更換更快的硬碟來解決問題。
- %util項的值也是衡量磁碟I/O的一個重要指標,如果%util接近100%,表示磁碟產生的I/O請求太多,I/O系統已經滿負荷的在工作,該磁碟可能存在瓶頸。長期下去,勢必影響系統的效能,可以通過最佳化程式或者通過更換更高、更快的磁碟來解決此問題。
Linux - iostatiostat 1 10iostat interval cont
上面每項的輸出解釋如下:
平均百分比為 = 總cpu佔百分比/cpu核心數
- %user 表示平均處理使用者進程所使用 CPU 的百分比。
- %nice 表示平均使用 nice 命令對進程進行降級時 CPU 的百分比。在之前的部分中已經對nice命令進行了介 紹。簡單來說,nice命令更改進程的優先順序。
- %system 表示平均核心進程使用的CPU百分比
- %iowait 表示平均等待進行 I/O 所使用的CPU時間百分比
- %irq 表示用於處理系統中斷的CPU百分比
- %steal 表示列顯示了在記憶體相對緊張的環境下pagein強制對不同的頁面進行的s
- %idle 顯示CPU的空閑時間百分比
- Blk_read/s 表示每秒讀取的資料區塊數。
- Blk_wrtn/s 表示每秒寫入的資料區塊數。
- Blk_read 表示讀取的所有塊數。
- Blk_wrtn 表示寫入的所有塊數。
可以通過Blk_read/s和Blk_wrtn/s的值對磁碟的讀寫效能有一個基本的瞭解,如果Blk_wrtn/s值很大,表示磁碟的寫操作很頻繁,可以考慮最佳化磁碟或者最佳化程式,如果Blk_read/s值很大,表示磁碟直接讀取操作很多,可以將讀取的資料放入記憶體中進行操作。
對於這兩個選項的值沒有一個固定的大小,根據系統應用的不同,會有不同的值,但是有一個規則還是可以遵循的:長期的、超大的資料讀寫,肯定是不正常的,這種情況一定會影響系統效能。
Linux - mpstatmpstat -P ALL 1 10
格式如下:mpstat -P ALL interval count
它顯示了系統中CPU的各種統計資訊。–P ALL 選項指示該命令顯示所有 CPU 的統計資訊.
- %user 表示處理使用者進程所使用 CPU 的百分比。
- %nice 表示使用 nice 命令對進程進行降級時 CPU 的百分比。在之前的部分中已經對nice命令進行了介紹。簡單來 說,nice命令更改進程的優先順序。
- %system 表示核心進程使用的 CPU 百分比
- %iowait 表示等待進行 I/O 所使用的 CPU 時間百分比
- %irq 表示用於處理系統中斷的 CPU 百分比
- %steal 表示列顯示了在記憶體相對緊張的環境下pagein強制對不同的頁面進行的s
- %idle 顯示CPU的空閑時間百分比
Linux - dstatdstat -tcdnmlpygs 1 10
格式:dstat -tcdnmlpygs interval count
dstat是多功能系統資源統計工具
dstat具體參數說明就不列出了,上述其他命令已經有說明
在擷取的資訊上有點類似於top、free、iostat、vmstat等多個工具的合集.
- CPU狀態:CPU的使用率
- 磁碟統計:磁碟的讀寫操作,這一欄顯示磁碟的讀、寫總數。
- 網路流量統計:網路裝置發送和接受的資料,這一欄顯示的網路收、發資料總數。
- 分頁統計:系統的分頁活動
- 系統統計:這一項顯示的是中斷(int)和環境切換(csw)
- 記憶體統計:這一項列出應用程式已使用實體記憶體,buffer,cache,free空閑記憶體
linux - iftopiftop
iftop顯示了系統上所有源主機或者目的主機網路頻寬使用的列表,此列表定期更新。
iftop部分參數說明與解釋
- 主機顯示
n: 切換是否解析主機名稱,你可以選擇顯示網域名稱還是 IP 位址;
s/d: 切換是否顯示源主機或者目的主機;
t: 切換主機接收和發送顯示的模式:兩行顯示、一行顯示、只顯示發送流量、只顯示發送流量;
- 連接埠顯示
N: 切換顯示服務名稱還是連接埠號碼,例如 ssh 或者 22;
S/D:切換是否顯示源主機連接埠或者目的主機連接埠;
p:切換是否顯示連接埠號碼;
- 排序顯示
1/2/3:根據最近 2 秒、10 秒、40 秒的平均網路流量排序;
<:根據源主機地址排序;
>:根據目的主機地址排序;
o:固定顯示當前串連,用來觀察當前串連的流量情況,避免重新整理後串連順序變化;
- 下面部分含義
TX:發送流量
RX:接收流量
TOTAL:總流量
Cumm:運行iftop到目前時間的總流量
peak:流量峰值
rates:分別表示過去 2s 10s 40s 的平均流量
linux - df & du查看磁碟空間使用、掛載和inode情況
du命令查看檔案和目錄磁碟使用的空間
輸出目前的目錄下各個子目錄所使用的空間:du -h --max-depth=1
按照子目錄大小排序(降序):du -s * | sort -rn | cut -f2- | xargs -d "\n" du -sh
linux診斷與調試部分命令使用匯總
//本機監聽連接埠來自用戶端串連數統計排序(降序)
lsof -i:9092 | awk '{print $9}' | cut -d ">" -f2 | awk '{ cidx=index($1,":");print substr($1,0,cidx-1)}' | sort | uniq -c | sort -rn
案例剖析案例1 建立大量網路連接數導致服務進程掛死或假死
當某台或幾台機器作為基礎服務元件或中介軟體節點(不一定為java,或python,go,c/c++等等)叢集部署時,會有大量用戶端會依賴此服務而串連此目的地組群。筆者遇到真實情況,叢集正常運行好長一段時間後,有一天突然發現叢集中某個節點處於不可用狀態。觀察其應用程式記錄檔沒有任何錯誤資訊,而且服務程式卻無法正常對外提供響應。
筆者通過相關命令按照以上幾個法則(cpu,記憶體,磁碟io,網路io,網路流量),當我們查看cpu,io,網路流量,磁碟容量,
發現監聽連接埠串連數數量巨大,存在問題,經定位分析發現某台用戶端主機建立大量網路連接沒有釋放。一般情況下linux系統最大檔案描述數量設定都非常大,到達100W以上,多數是其他資源先消耗。
下面是類比當時環境的一幅圖。
[lizhitao@host ] netstat -an | grep 9094
[lizhitao@host ] lsof -i:9094 | awk '{print $9}' | cut -d ">" -f2 | awk '{ cidx=index($1,":");print substr($1,0,cidx-1)}' | sort | uniq -c | sort -rn
很明顯mafka.sankuai.com這台主機建立了大量串連,導致資源耗盡。
說明:netstat一般顯示是ip,lsof一般顯示主機名稱,因為用戶端串連比較多(在TCP裡好像每個socket佔用500byte),很難一下子看出哪個客戶主機數比較多,所以2命令組合使用就比較方便。
擴充閱讀:
上面案例是網路連接(網路檔案描述符)問題,而有些可能是磁碟檔案(描述符)開啟量巨大,而沒有釋放資源導致程式bug。
典型就是儲存圖片或小檔案的Distributed File System。
- 遞迴尋找某個目錄中所有開啟的檔案
[lizhitao@host ] lsof +D /DIR/
lsof的列表中Type為REG和DIR分別表示開啟磁碟檔案和目錄
[lizhitao@host ] lsof -p [pid] | "REG" //列舉該進程所有開啟的磁碟檔案.
然後通過計算和分析就能知道是否有大量磁碟檔案沒有釋放,然後定位出問題的代碼塊.
案例2 線上java服務進程突然cpu佔用很高。
java進程cpu的消耗排序
[lizhitao@host ] ps p 31476 -L -o pcpu,pid,tid,time,tname,stat,psr | gawk '{printf("%s %d %d %s %s %s %x\n",$1,$2,$3,$4,$5,$6,$3) }' | sort -n -k1 -r
假如上述圖片列表中顯示的cpu消耗很高且大約80%cpu,則我們可以通過上述命令操作,找到對應線程號nid=31510轉換為十六進位0x7b16
[lizhitao@host ] jstack 31476 | grep "7b16"
[lizhitao@host ] jstack 31476
縮小代碼排查範圍,順藤摸瓜找到對應的呼叫堆疊資訊和代碼,然後對相關代碼邏輯進行分析。
案例3 某個進程啟動時無法建立檔案
如果遇到上述錯誤,可以先檢測一下硬碟狀態資訊(一般是這類問題機率不大,除非是資料庫或做儲存用的伺服器)
請參考硬碟檢測smartctl:Linux系統下檢測硬碟的健康狀態
Linux硬碟的檢測
如果磁碟狀態一切正常,則分析可能為掛載磁碟空間佔滿。
執行 :df -h 查看磁碟空間佔用情況
然後到相應的應用程式軟體部署目錄或資料存放區目錄下執行:
du -s * | sort -rn | cut -f2- | xargs -d "\n" du -sh
就可以順利找到佔用空間比較大的目錄,然後做相應處理。
總結
以上,就是我在linux下後端診斷與調試時遇到的問題和收穫,以及解決辦法,下面是我對這些方面的總結:
linux下後端診斷與調試是複雜而比較有挑戰性工作,需要操作者或工程師綜合運用各種手段找到問題所在,從而逐步地縮小範圍,定位到某個點上,不同的應用程式也會不一樣,比如說:普通的java(tomcat)服務與memcached分布式緩衝遇到問題也不盡相同。首先我們可以從系統層面上劃清界限,是作業系統,本機服務程式,還是其他主機訪問導致的。通過六種手段,比如說網路io,磁碟io,記憶體,cpu,開啟檔案,線程等,分析其瓶頸方向。所以沒有一種命令或方法能“包治百病”,需要工程師在不同應用環境下,巧妙選擇且綜合運用不同手段,搭配多種命令組合才能完成。
參考
http://kodango.com/using-iftop
http://www.vpsee.com/2009/11/linux-system-performance-monitoring-io/
http://blog.csdn.net/guoguo1980/article/details/2324454
http://coolshell.cn/articles/7490.html