警惕麥咖啡的"緩衝區溢位保護"引起的ASP.NET 中 System.OutOfMemoryException 的錯誤

來源:互聯網
上載者:User

   客戶服務器上的系統已經穩定運行好幾年了,在客戶更換過新伺服器(雙4核CPU,8G記憶體)一段時間後近期突然無法正常使用,開啟首頁或登入成功後,立即就出現 System.OutOfMemoryException 的錯誤,系統徹底崩了。

   詢問過穀哥和度娘後,得到的結論是:

 

在ASP.NET Web(U8Soft.AppServer)伺服器上,ASP.NET所能夠用到的記憶體,通常不會等同於所有的記憶體數量。在machine.config設定檔(目錄)中,配置節中有一個屬性“memoryLimit”,這個屬性的值是一個百分值,預設為“60”,即指定了ASP.NET進程(在工作管理員中大家就可以看到ASP.NET的進程,IIS5中為aspnet_wp,IIS6中為w3wp)能夠使用所有實體記憶體的60%。當ASP.NET使用的記憶體量超過這個限額時,IIS會開始自動回收(recycle)進程,即建立一個新的進程去負責應付Http請求,而將舊進程所佔用的記憶體回收。 ??當我們有一台很大記憶體的伺服器時,“memoryLimit”這個值是需要進行適當的調整的。比如我們準備了一台4G記憶體的伺服器,那麼4G×60%=2.4G。但是,對於Win32作業系統,一個進程所能佔用的所有記憶體空間只有2G。當ASP.NET進程佔用的記憶體開始達到2G時,由於它並沒有達到2.4G的“回收閾值”,所以IIS不會啟動recycle進程操作,但是由於Win32的限制,實際上已經不能給這個進程分配更多的記憶體了,於是,OutOfMemoryException就很可能會被拋出了。為了避免這樣的情況,我們就必須將“memoryLimit”適當調小,以讓IIS更早的進行進程回收。 ??微軟推薦的ASP.NET進程佔用記憶體是不超過60%,並最好使計算出的實際值不超過800M。就是說,對於一台4G記憶體的伺服器,最好將“memoryLimit”屬性設定成“20”。設定一個適當的回收閾值,讓IIS適時的進行進程回收,對於保證整個伺服器的穩定運行,避免OutOfMemoryException是非常重要的。 ??在IIS6中,ASP.NET進程的回收閾值不再由配置節中的“memoryLimit”屬性決定,而是由IIS管理器中的應用程式集區配置中的設定決定。 ??但是,即使正確設定了這些配置,也不能保證完全避免OutOfMemoryException的發生,原因可能是多樣而複雜的,比如記憶體回收操作可能耗時太多等等。開發人員要注意的,就是在代碼中時刻牢記不要無謂的使用和浪費記憶體。

 

  按此方法,幾經修改配置,仍無任何效果,於是進一步懷疑是各殺毒軟搗的鬼,特別是麥咖啡的"緩衝區溢位保護",一看就是做記憶體訪問限制的,於是第一個先將它停止,結果發現在將麥咖啡的"緩衝區溢位保護"停止後,系統復原正常。但過幾十秒鐘後,又複崩潰。Why? 再檢查麥咖啡,發現"緩衝區溢位保護"自動啟動了......採用了N種方法將其停用無果,求助麥咖啡的客服無用,只能將麥咖啡從伺服器上徹底刪除,於是一切又恢複了正常。

     

     最近進一步研究此問題,發現有這樣的技術資料:

 

 

多處理器(或多核心)電腦上的 .NET CLR 的 Garbage Collection (GC) 機制預設是使用 Server Mode (伺服器模式) 在運作的,換句話說,就是「每一顆 CPU 都會有獨立的 GC 記憶體空間(堆積, Heap)」,所以如果你的 GC 記憶體空間 用掉了 500MB 且你有 4 顆 CPU 的話,就等於耗費了 2GB 的記憶體,進而發生 System.OutOfMemoryException 例外狀況!

要解決這個問題的方式就是將 GC 設定為 Workstation Mode (工作站模式),這樣就可以整台主機共用同一個 GC Heap,以節省記憶體的使用。要將預設的 GC 修改成 Workstation Mode 必須要修改 %WINDIR%\Microsoft.NET\Framework\v2.0.50727\Aspnet.config 檔案 ( 如果是 .NET 1.1 要修改 %WINDIR%\Microsoft.NET\Framework\v1.1.4322\Aspnet.config 檔案 ):

 

預設的 Aspnet.config 長這樣:

 

 

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <runtime>
        <legacyUnhandledExceptionPolicy enabled="false" />
        <legacyImpersonationPolicy enabled="true"/>
        <alwaysFlowImpersonationPolicy enabled="false"/>
        <SymbolReadingPolicy enabled="1" />
    </runtime>
</configuration>

 

需加上一行 <gcServer enabled="false"/> 如下:

 

 

 

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <runtime>
        <gcServer enabled="false" />
        <legacyUnhandledExceptionPolicy enabled="false" />
        <legacyImpersonationPolicy enabled="true"/>
        <alwaysFlowImpersonationPolicy enabled="false"/>
        <SymbolReadingPolicy enabled="1" />
    </runtime>
</configuration>

 

不過像這種出現 Out of Memory 的異常狀況在 64 位元位的作業系統幾乎不會出現問題,所以如果你是用 64 位元的作業系統(如:Windows Server 2003 64bit ) 的話,是不太需要做這樣的調整的,但你的記憶體還是要夠多才行,否則過多的分頁況還是會降低你 ASP.NET 就用程式的執行效率!

除了這點之外,在正式(Production)環境中的 ASP.NET 應用程式一定要在 web.config 中關閉開發時期設定的 debug 與 trace,才不會記憶體造成額外的負擔。因為 ASP.NET應用程式在啟用debug mode 的時候所有的 Symbol 檔(*.pdb)都會被載入記憶體中,不但會消耗不少記憶體,也會降低執行效率。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.