當你你有1000個w3wp.exe文件在eventviewer中意外停止,或者您的進程以某種奇怪的未定義方式退出,您不知道原因。
當一個進程崩潰或退出時,將觸發一個稱為EPR(Exit process)的特殊事件,因此使用類似於windbg.exe文件我們可以附加到進程中,等待epr被拋出,然后進行內存轉儲。安裝windows調試工具時,會得到一個名為adplus的vbs腳本,它將為您自動執行此操作,並打印進程生命周期中發生的大多數異常的日志。
調試提示:當您在-crash模式下打開一個轉儲時,您將自動定位到崩潰發生時處於活動狀態的線程(最有可能是可疑的線程)。如果您切換線程並想返回出錯線程,請鍵入~列出所有線程,錯誤線程將被標記為一個點。
如果dump只顯示進程中的一個活動線程,並且該線程是主線程,則該進程可能被外部的東西(運行狀況監視、低系統內存、iisreset等)終止
不分先后順序,以下是我們看到的支持率最高的一些:
Stack Overflow Exceptions
當為線程的堆棧分配的內存用完時,將發生堆棧溢出異常。默認情況下,它是1 MB,所以你的調用堆棧可能很深,所以大多數情況下發生這種情況是因為無限遞歸,也就是說,function調用FunctionB,后者再次調用FunctionB,后者再次調用FunctionB。。。沒有停止條件。
不幸的是,異常處理應用程序塊的錯誤使用是一個相當常見的模糊的無限遞歸情況。想象一下這個場景:你的應用程序得到一個異常,異常處理程序啟動,你已經將它設置為記錄到一個文件中。在記錄日志時,您會得到某種類型的異常(比如訪問被拒絕),並且您已經設置了異常處理程序來處理此異常。在這種情況下,您將在一個無限遞歸循環中處理一個異常,拋出另一個異常,處理它,拋出另一個。。。你明白要點了。這個故事的寓意是什么?不要在異常處理程序中使用異常處理程序來處理異常。
如果您運行“kb2000”(查看本機堆棧)和“!clrstack”(從sos.dll要查看托管堆棧),您可以找到遞歸模式以跟蹤遞歸發生的位置/原因。
Out Of Memory Exceptions
大多數情況下,發生內存不足異常是由設計問題引起的,在設計問題中,緩存或會話作用域中存儲的內存過多。如果以正確的方式使用緩存,那么緩存對於提高性能是非常有用的,也就是說,緩存的數據最多,而且緩存的時間不會超過需要的時間。在舊的ASP中,如果將對象存儲在session范圍內,就會出現問題,相信我,這是一種偽裝,因為開發人員只在session范圍內存儲了最必要的項。例如,在會話范圍內存儲大型數據集通常會適得其反,因為您減少了網站可以處理的並發用戶數,而且當內存足夠大時,在緩存中進行垃圾收集和搜索所需的時間可能比從數據庫中請求數據的開銷要多真的需要它。
在何時應該在會話/緩存中存儲內容以及何時不應該存儲時,這里沒有一刀切的解決方案。最好的做法是在早期階段,確定應用程序需要能夠處理的用戶數,並在此基礎上確定每個用戶可以允許的存儲量。然后對超過最大用戶數的用戶進行壓力測試,以確保你能應付。最好是對處於會話狀態的對象進行壓力測試,看看性能如何。不同的用戶數量不同。
在生產過程中,內存問題是很難解決的,因為它們通常需要大量的重新設計,所以在早期階段花費一分錢可以節省很多錢。
調試提示:運行!dumpheap -type System.Web.Caching.Cache獲取緩存根,然后對這些地址進行!do objsize,以了解您在緩存中為不同的應用程序存儲了多少。(注意:InProc會話狀態也存儲在緩存中)
Unhandled exception in COM Component
當您因為堆損壞而崩潰時,出錯的堆棧通常位於ntdll中的堆分配函數中,要解決此問題,您需要使用GFlags或PageHeap運行,以便能夠當場抓到小偷。然而,之所以如此難以捕捉,是因為這些問題非常隨機,很難重現。
如果發生崩潰,並且活動堆棧的頂部包含GC函數,則開始在代碼中查找pinvoke,看看是否傳遞的緩沖區太小。
如果你的進程死了,同時你看到內存/available兆字節的大幅度下降,達到0,這可能會導致進程崩潰。當然,這里的任務是檢查是什么進程偷走了內存。
External process kills/Recycles the process
無數次,當我有一個客戶在崩潰模式下連接adplus時,我會發現內存轉儲,進程被外部的東西殺死了。我想添加這個問題,因為通常當你對崩潰進行故障排除時,這並不是你要排除的崩潰的真正原因(只有在極少數情況下),而是有人運行iisreset或者在不知道你有一個調試程序等待崩潰的情況下殺死了進程。所以如果你正在排除一個崩潰並得到一個內存轉儲。檢查事件日志以確保沒有人運行iisreset,因此這是導致崩潰轉儲的原因。這樣可以節省你幾個小時去尋找車禍的罪魁禍首。
另一個奇怪的地方是安裝了某種監視軟件來監視服務器是否按預期服務頁面,如果沒有,則關閉進程。但通常這也會在eventviewer中記錄發生的事件。
Health monitoring settings
當然,我知道我們設置為每24小時循環一次進程,或者如果服務器空閑超過20分鍾,但無論如何值得一提的是,因為我們經常遇到這些問題。同樣,這里,通常會在事件日志中記錄一個事件,說明進程被回收的原因,但故事的寓意是在iis或中簡要查看應用程序池的運行狀況監視設置計算機配置看看你打開了什么回收意見,這樣你以后就不會有驚喜了。
發生崩潰的原因比上面提到的要多,但它們通常都是相當模糊的,所以我希望這篇文章能讓你對如何開始尋找進程突然失效有一點了解。