1. 程式人生 > >中小研發團隊架構實踐之WinDbg

中小研發團隊架構實踐之WinDbg

生產環境偶爾會出現一些異常問題,WinDbg或GDB是解決此類問題的利器。除錯工具WinDbg如同醫生的聽診器,是系統生病時做問題診斷的逆向分析工具,Dump檔案類似於飛機的黑匣子,記錄著生產環境程式執行的狀態。本文主要介紹了除錯工具WinDbg和抓包工具ProcDump的使用,並分享一個真實的案例。N年前不知誰寫的程式碼,導致每一兩個月偶爾出現CPU飆高的現象。我們先使用ProcDump在生產環境中抓取異常程序的Dump檔案,然後在不瞭解程式碼的情況下通過WinDbg命令進行分析,最終定位到有問題的那行程式碼。

一、診斷工具簡介 1.1 WinDbg

WinDbg是在Windows平臺下的、強大的使用者態和核心態除錯工具。相比較於Visual Studio,它是一個輕量級的除錯工具,所謂輕量級指的是它的安裝檔案大小較小,但是其除錯功能,卻比VS更為強大。它的另外一個用途是可以用來分析Dump資料。WinDbg是Microsoft公司免費偵錯程式除錯集合中的GUI的偵錯程式,支援Source和Assembly兩種模式的除錯。WinDbg不僅可以除錯應用程式,還可以進行Kernel Debug。結合Microsoft的Symbol Server,可以獲取系統符號檔案,便於應用程式和核心的除錯。WinDbg支援的平臺包括x86、IA64、AMD64。雖然WinDbg也提供圖形介面操作,但它最強大的地方還是有著強大的除錯命令,一般情況會結合GUI和命令列進行操作,常用的檢視有:區域性變數、全域性變數、呼叫棧、執行緒、命令、暫存器、白板等。其中“命令”檢視是預設開啟的。

1.2 DebugDiag

DebugDiag最初是為了幫助分析IIS的效能問題而開發的,它同樣可以用於任何其他的程序。DebugDiag工具主要用於幫助解決如掛起、 速度慢、 記憶體洩漏或記憶體碎片,和任何使用者模式程序崩潰等問題。該工具包括附加除錯指令碼,側重於網際網路資訊服務(IIS)應用程式、 Web資料訪問元件、 COM+和相關Microsoft技術、SharePoint和.NET。它提供可擴充套件物件模型中的COM物件的形式,並具有一個內建的報告框架提供的指令碼主機。它由3 部分組成,包括除錯服務、 偵錯程式主機和使用者介面。

1.3 ProcDump

ProcDump是System Internal提供的一個專門用來監測程式CPU高使用率從而生成程序Dump檔案的工具。ProcDump可以根據系統的CPU使用率或者指定的效能計數器來針對特定程序生成一系列的Dump檔案,以便除錯者對事故原因進行分析。

二、診斷工具下載 三、獲取異常程序的Dump檔案

有以下四種方式獲取Dump檔案,具體如下:

3.1 通過【工作管理員】獲取Dump檔案,這樣獲取的是MinDump

3.2 利用WinDbg的adplus獲取Dump檔案,這樣獲取的是FullDump

3.3 通過DebugDiag建立.NET異常轉儲Dump檔案

3.4 通過ProcDump抓取異常執行緒Dump檔案

現在重點介紹通過ProcDump抓取異常執行緒Dump檔案,使用方法如下:

a. 命令列:
procdump [-a] [[-c|-cl CPU usage] [-u] [-s seconds]] [-n exceeds] [-e [1 [-b]] [-f <filter,...>] [-g] [-h] [-l] [-m|-ml commit usage] [-ma | -mp] [-o] [-p|-pl counter threshold] [-r] [-t] [-d <callback DLL>] [-64] <[-w] <process name or service name or PID> [dump file] | -i <dump file> | -u | -x <dump file> <image file> [arguments] >] [-? [ -e]
b. 例項:

procdump -c 70 -s 5 -ma -n 3 w3wp

當系統CPU使用率持續5秒超過70%時,連續抓3個Full Dump。

procdump outlook -p "\Processor(_Total)\% Processor Time" 80

當系統CPU使用率超過80%,抓取Outlook程序的Mini Dump。

procdump -ma outlook -p "\Process(Outlook)\Handle Count" 10000

當Outlook程序Handle數超過10000時抓取Full Dump

procdump -ma 4572

直接生成程序號為4572的Full Dump。

 

下圖是在WindgbHighCpu程序中造成High CPU時執行ProcDump命令的執行效果,可以看到在CPU每次持續5秒達到5%後就會生成相應的Dump檔案,共生成了3份Full Dump檔案:

c. 注意:
  • ProcDump需要程序已經啟動,並且中途不能停止。比如需要抓取IIS Worker Process的High CPU Dump,由於IIS Worker Process預設會配置Idle Timeout = 20 min,即該程序在20分鐘內沒有任何請求的話就會自動結束,這種情況下ProcDump也會自動結束。需要重新執行命令。因此如果目標程式存在這樣的配置,需要暫時將該配置取消。
  • 有些系統管理員希望能夠執行該工具後退出使用者session,ProcDump是做不到的,如果有這種需求可以考慮使用DebugDiag。
  • 在除錯High CPU問題的時候經常用到的一個命令是!runaway,但是有些時候!runway在ProcDump抓取Dump檔案的過程中執行不出來,報錯資訊如下:
0:000> !runaway ERROR: !runaway: extension exception 0x80004002. "Unable to get thread times - dumps may not have time information"

解決的方法是將Debugging Tools for Windows (WinDbg)安裝目錄下的dbghelp.dll拷貝到procdump.exe所在目錄下,然後再執行命令抓取Dump。 

四、WinDbg使用方法

操作步驟如下:

4.1 抓取異常程式的Dump檔案 4.2 設定符號表

符號表是WinDbg關鍵的“資料庫”,如果沒有它,WinDbg基本上就是個廢物,無法分析更多問題。所以使用WinDbg設定符號表,是必須要走的一步。

a、執行WinDbg軟體,然後按【Ctrl+S】彈出符號表設定窗。

b、將符號表地址:SRV*C:\Symbols*http://msdl.microsoft.com/download/symbols 貼上在輸入框中,點選確定即可。點選確定之前,請先確認紅色字的資料夾是否已被新建。

注:紅色字表示符號表本地儲存路徑,建議固定路徑,可避免符號表重複下載。

4.3 學會開啟第一個Dump檔案

       

 

當你拿到一個Dump檔案後,可使用【Ctrl+D】快捷鍵來開啟一個Dump檔案,或者點選WinDbg介面上的【File=>Open Crash Dump...】按鈕,來開啟一個Dump檔案。第一次開啟Dump檔案時,可能會收到如下提示,出現這個提示時,勾選“Don't ask again in this WinDbg session”,然後點否即可。

當你想開啟第二個Dump檔案時,可能因為上一個分析記錄未清除,導致無法直接分析下一個Dump檔案,此時你可以使用快捷鍵【Shift+F5】來關閉上一個對Dump檔案的分析記錄。

4.4 通過簡單的幾個命令學會分析Dump檔案

分享一個數據庫連線超時的Dump案例的分析過程:

當你開啟一個Dump檔案後,可能因為太多資訊,讓你無所適從,不過沒關係,我們只需要關注幾個關鍵資訊就可以了。

a. 載入SOS擴充套件命令

載入SOS之前,先確定SOS的位置和版本,確定方法如下:

如果安裝了Visual Studio,那麼先按照如下步驟開啟VS的命令列:

然後,在開啟的VS命令列中輸入【where sos.dll】,使獲得SOS的位置和版本:

 

確定完SOS位置和版本號後,開始載入SOS擴充套件命令:

.load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\SOS.dll

如下圖所示:

b. 使用!clrstack命令來檢視當前的呼叫堆疊資訊

如下圖所示:

c. 使用!dso命令來檢視堆疊上的所有物件詳細資訊

如下圖所示:

綜合以上分析可以大膽地猜測Common.cs 中第16行“Data Source=***;Initial Catalog=***;Persist Security Info=True;User ID=sa;Password=***”的這個資料庫連線字串應該有問題,然後到程式碼中相應的地方進一步確認和修改就可以了。        

五、一個真實案例

分享筆者工作過的一家公司某業務系統CPU飆高90%以上的Dump分析過程案例,步驟如下:

5.1 使用ProcDump抓包 5.2 載入SOS擴充套件命令
.load C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos.dll

5.3 分析

執行!runaway命令,檢視執行緒使用CPU時間情況,如下圖所示。著重分析前面幾個執行緒。 

執行~22s命令,進入到執行緒22,如下圖所示:

執行!clrstack命令檢視當前執行緒堆疊變數值的資訊,從圖中可以猜出大概是ExecuteNonQuery()這方法有點問題,如下圖所示:

再執行!dso命令可以檢視堆疊上的所有物件詳細資訊,如下圖所示:

從圖中看,造成CPU飆高的罪魁禍首多半由SQL Server執行

INSERT INTO [dbo].[tbl_Interface_ProcessLog] (IKey,Username,ClientIP,Module,OrderNo,LogType,Content) VALUES (@IKey,@Username,@ClientIP,@Module,@OrderNo,@LogType,@Content)

這條語句時產生異常引起,然後到原始碼中找出相應的語句,經過進一步的確認、修改和重新發布後就解決了CPU飆高的問題。

 

至此,掌握幾個簡單的WinDbg命令之後,基本上絕大多數Dump大家都可以獨立分析了。當然WinDbg是個強大的工具,同時產生CPU飆高和記憶體洩漏的原因也有很多。如果想分析得足夠準確,那麼就只有多學多練,多去分析。因為掌握WinDbg分析除了需要懂得幾個命令之外,經驗更加重要,最後再補充兩點:

  1. WinDbg不是專門用於除錯.NET程式的工具,它更偏向於底層,可用於核心和驅動除錯,特別是對於某些相當疑難的問題除錯有所幫助,例如記憶體洩漏等問題。進行普通的.NET程式除錯還是使用微軟專為.NET開發所提供的除錯工具更方便一些。
  1. SOS擴充套件命令中最有用的命令是!help,使用該命令可以列出所有可用的SOS擴充套件命令列表,使用!help [SOSCommandName]可以檢視每一個具體擴充套件命令的詳細使用說明。例如!help dumpheap就可以檢視!dumpheap這個擴充套件命令的具體使用方法。多多利用!help命令可以很快上手SOS。
六、Demo下載及更多資料