問題
我們有一個 ASP.NET 的系統部署到 IIS 上(Windows 2012, .NET 4.x),有時候會導致 w3wp.exe 吃掉所有的 CPU 資源,一直要等到應用程式回收後,程式再重新啟動後就正常了。這種狀況不定期會發生。
解法
我們可以使用 WinDbg 來找出導致 IIS CPU 100% 的原因,方法如下,
透過「工作管理員」來「建立傾印檔案」
當發生 IIS 導致 CPU 100% 時,開啟「工作管理員」,按右鍵選取「建立傾印檔案」。要依 Web 應用程式的平台(x86/x64)來開啟「工作管理員」(x86的工作管理員在 C:\Windows\SysWOW64\taskmgr.exe )。安裝 WinDbg
請參考 Debugging Tools for Windows (WinDbg, KD, CDB, NTSD) 來安裝對應的版本。設定 Symbol Path
先建立一個 C:\RTX64_SYMBOLS 目錄(依您自行定義),然後開啟 Command 設定 _NT_SYMBOL_PATH 的環境變數,如下,1
set _NT_SYMBOL_PATH=srv*C:\RTX64_SYMBOLS*https://msdl.microsoft.com/download/symbols
所以在 command 中,輸入 set 後,就可以看到 _NT_SYMBOL_PATH 的設定值哦,
當然,如果常常會用到的話,就直接設定到 環境變數之前,下次 debug 時,就不用再設定一次了哦! 詳細請參考Set up your system to use Microsoft’s public Symbol Server
在 WinDbg 中找問題
載入 sos.dll
1
.load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos.dll
WinDbg 有 x86/x64 的版本,我是使用 x64 的版本,所以 sos.dll 的路徑是 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos.dll,您輸入如果發生錯誤的話,請使用 C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll 。
設定 Symbol 檔目錄
1
2!sym noisy
.cordll -ve -u -l透過 !runaway 顯示Threads所佔的時間
輸入 !runaway 後,會顯示各 Thread 所花費的時間,花最多的會在最上面,如下圖,1
!runaway
透過 ~[thread]s 切換到該 thread 的位置
由上圖所示,Thread 40 佔最多時間,所以我們切到它的位罝去,1
~40s
透過 !clrstack 來查看呼叫堆疉
1
!clrstack
從上圖可以發現,應該是有關 Dictionary 操作的問題,而它是由我們系統中 TemplateCfg.initial() 這個 Method 所引起的。
檢視並調整程式碼
開啟 TemplateCfg 程式碼,在 initial 這個 Method 之中會建立 Dictionary 物件,Clear 它,並 Insert 資料,但這些 Dictionary 的變數卻又設定成 static 。即然這些 Dictionary 是 static 的,而且它們值又都是相同的,就沒有必要每次 request 時,就重新建立並 insert 這些資料。
所以將 initial 裡面的 Code 搬到 static constructor 。
調整完程式碼後,從去年觀察到目前,已經沒有再發生 CPU 100% 的狀況。
參考資料
Debugging in Production Part 1 - Analyzing 100% CPU Usage Using Windbg
WinDBG 應用實例:找出 ASP.NET CPU 100% 原因
Debugging Tools for Windows (WinDbg, KD, CDB, NTSD)
Set up your system to use Microsoft’s public Symbol Server
High CPU Hangs - 05
中小型研发团队架构实践:生产环境诊断利器WinDbg帮你快速分析异常情况Dump文件
Intro to WinDBG for .NET Developers
.NET Debugging Demos Lab 4: High CPU Hang – Review