標籤:for mem 符號 需要 export call 使用命令 frame 路徑
公司為了節省成本,最近有一批伺服器降了配置,CPU從8核降到了2核。本身是小網站,訪問量也不高,CPU總是會飆到100%而且可以一直持續幾個小時,直接強制結束進程可以維持幾個小時,幾個小時後又一樣,營運那邊總是受到cpu的警告簡訊很是苦惱,按理來說就算降低了配置也不至於會讓CPU一直100%。
以下就分享本次使用 WinDbg 找出 CPU 100% 問題的經驗:
1.建立Dump檔案
進程注意是32位的,還是64位。64位的進程可以直接建立,32位進程請使用C:\Windows\SysWOW64\taskmgr.exe 工作管理員進行建立,否則放到windbg中會報錯。
2.用windbg載入dump檔案
32位的進程使用x86的windbg載入,64為的進程使用x64的windbg來載入。https://github.com/LonelyCodelang/Tools/tree/master/Windbg_x86_x64
3.配置調試環境
開啟後,會顯示程式當時運行所在的環境,此時,會提示符號檔案沒有發現:
*** ERROR: Symbol file could not be found. Defaulted to export symbols for ntdll.dll -
如果不配置,使用命令的時候會提示錯誤,比如:
0:000> .loadby sos clrjit0:000> !tp*** ERROR: Symbol file could not be found. Defaulted to export symbols for clr.dll - ************* Symbol Loading Error Summary **************Module name Errorclr PDB not found : e:\appserver\symbols\dll\clr.pdb
e:\appserver 是我的dmp檔案所在的目錄,它預設是到symbols 子目錄去找符號檔案去了。
然後,配置下使用此檔案的調試環境。
在功能表命令 File->Symbol path... 開啟對話方塊,選擇瀏覽,找到dmp檔案所在目錄相關的程式檔案目錄 E:\AppServer ,該目錄下面有程式相關的 exe,pdb 檔案。
輸入下面的命令:
0:000> .sympath+ c:\symbolsSymbol search path is: E:\AppServer;c:\symbolsExpanded Symbol search path is: e:\appserver;c:\symbolsError: Attempts to access ‘c:\symbols‘ failed: 0x2 - 系統找不到指定的檔案。************* Symbol Path validation summary **************Response Time (ms) LocationOK E:\AppServerError
這裡不用管,這個檔案夾後面可以產生。
0:000> .symfix0:000> .symfix+ c:\symbols0:000> .sympathSymbol search path is: srv*Expanded Symbol search path is: SRV*c:\symbols*http://msdl.microsoft.com/download/symbols************* Symbol Path validation summary **************Response Time (ms) LocationDeferred
這下對了。
執行下 reload命令:
0:000> .reload............................................................................................................................................
接著執行下面:
0:000> .loadby sos clr0:000> !tpThe version of SOS does not match the version of CLR you are debugging. Pleaseload the matching version of SOS for the version of CLR you are debugging.CLR Version: 4.0.30319.296SOS Version: 4.6.96.0Failed to load data access DLL, 0x80004005
這裡提示說SOS的版本更CLR不匹配,這裡需要找到當時產生Dump檔案所在的伺服器上的 sos.dll,注意,因為伺服器程式是64位的,所以必須在 .Net Framework64 目錄去找,同時把 mscordacwks.DLL 檔案一起拷貝過來(先暫時不用,下面馬上會講到)。
剛才這個命令執行後,我們驚喜的發現,c:\symbols 目錄自己建立了,並且下載了 clr.pdb等幾個目錄,這是再將剛才伺服器上拷貝的 sos.dll, mscordacwks.dll ,放到本地機器的 c:\symbols 目錄下面。
再次執行這幾個命令:
0:000> .reload............................................................................................................................................0:000> .loadby sos clr0:000> !tpThe version of SOS does not match the version of CLR you are debugging. Pleaseload the matching version of SOS for the version of CLR you are debugging.CLR Version: 4.0.30319.296SOS Version: 4.6.96.0Failed to load data access DLL, 0x80004005
還是報錯,看來 sos.dll 沒有載入正確,用下面的命令:
0:000> .load c:\symbols\sos.dll0:000> .loadby sos clr0:000> !tp
這裡load命令必須帶SOS.dll的路徑。載入了它,然後執行 .loadby sos clr ,表示調試.NET託管程式。
開始漫長的等待,程式視窗提示:
*BUSY*
Downloading symbols for [clr.pdb] /
等到相關的符號檔案全部下載完畢,終於出現了久違的成功介面:
CPU utilization: 11%Worker Thread: Total: 8 Running: 0 Idle: 8 MaxLimit: 32767 MinLimit: 8Work Request in Queue: 0--------------------------------------Number of Timers: 14--------------------------------------Completion Port Thread:Total: 1 Free: 1 MaxFree: 16 CurrentLimit: 0 MaxLimit: 1000 MinLimit: 8
4.找出佔用CPU最多的Thread,並切換到改Thread
使用!runaway 找出每個Thread消耗的cpu時間。最耗時的線程ID是17,造成CPU100%的就是此線程。
~17s
切換到此線程
5.使用 !clrstack 列出 Thread 27 的 Callstack
從這裡就可以定位到具體的方案,是RabbitMQ消費方法的線程造成的,具體就可以看內部方法的實現,然後進行最佳化。
相關參考文章:
https://blogs.msdn.microsoft.com/tess/2010/09/29/capturing-memory-dumps-for-32-bit-processes-on-an-x64-machine/
https://www.cnblogs.com/bluedoctor/p/4813125.html
https://stackoverflow.com/questions/16422577/sos-does-not-support-the-current-target-architecture/16422887
WinDbg調試分析 asp.net網站 CPU100%問題