2012-11-14 18 views
7

我已閱讀thisthisthisthis加上一打其他職位/博客。Application_End應該觸發一個自動App Pool Recycle嗎?

我在經常回收的共享主機中有一個ASP.Net應用程序。我們使用NLOG並在Global.asax的

void Application_Start(object sender, EventArgs e) 
{ 
    NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); 
    logger.Debug("\r\n\r\nAPPLICATION STARTING\r\n\r\n"); 
} 
protected void Application_OnEnd(Object sender, EventArgs e) 
{ 
    NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); 
    logger.Debug("\r\n\r\nAPPLICATION_OnEnd\r\n\r\n"); 
} 

void Application_End(object sender, EventArgs e) 
{ 
     HttpRuntime runtime = (HttpRuntime)typeof(System.Web.HttpRuntime).InvokeMember("_theRuntime", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetField, null, null, null); 

if (runtime == null) 
    return; 

string shutDownMessage = (string)runtime.GetType().InvokeMember("_shutDownMessage", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField, null, runtime, null); 

string shutDownStack = (string)runtime.GetType().InvokeMember("_shutDownStack", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField, null, runtime, null); 

ApplicationShutdownReason shutdownReason = System.Web.Hosting.HostingEnvironment.ShutdownReason; 

NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); 
logger.Debug(String.Format("\r\n\r\nAPPLICATION END\r\n\r\n_shutDownReason = {2}\r\n\r\n _shutDownMessage = {0}\r\n\r\n_shutDownStack = {1}\r\n\r\n", 
       shutDownMessage, shutDownStack, shutdownReason)); 
} 

void Application_Error(object sender, EventArgs e) 
{ 
    NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); 
    logger.Debug("\r\n\r\nApplication_Error\r\n\r\n"); 

} 

我們的日誌文件中充斥着「應用程序啓動」項下面的代碼,但既不Application_OnEndApplication_End,也不Application_Error是不斷在這些自發的重新發射。我知道他們正在工作,因爲有觸摸web.config或/ bin文件的條目。我們還運行了內存過載測試,並且可以觸發中的OutOfMemoryException

我們試圖確定虛擬內存限制是否導致回收。我們在整個代碼中都添加了GC.GetTotalMemory(false),但是這是針對的所有.Net,而不僅僅是我們的應用程序池,對不對?我們也試過

var oPerfCounter = new PerformanceCounter(); 
oPerfCounter.CategoryName = "Process"; 
oPerfCounter.CounterName = "Virtual Bytes"; 
oPerfCounter.InstanceName = "iisExpress"; 
logger.Debug("Virtual Bytes: " + oPerfCounter.RawValue + " bytes"); 

但是沒有共享主機的權限。

我監測與用ANTS內存分析器連接,似乎無法找到元兇的再循環生產同一請求dev的服務器上的應用程序。我們還使用dev中附帶的調試器來運行它,以檢查可能導致應用程序中止的衍生線程中的未捕獲異常。

我的問題是:

  • 我怎樣纔能有效地監控共享主機告訴我的應用程序是多少之前,應用循環消耗內存使用情況?
  • 爲什麼不調用global.asax中的Application_ [End/OnEnd/Error]處理程序?
  • 我該怎樣才能確定是什麼導致這些回收?

謝謝。

編輯:由@JaniHyytiäinen基於答案

場景: 線程#1開始,其次是線#2。線程#1命中內存限制但繼續處理。線程#3開始。線程#1完成,但#1在#1達到內存限制後超過60秒。

游泳池然後不正常地中止?什麼http響應將#2 &#3收到(這些是AJAX調用,但我在Fiddler中得到504錯誤)?
接受#3的請求還是隻是排隊直到新的池啓動?
有什麼辦法可以知道內存限制已經被觸發或將要被觸發嗎?

任何策略的歡迎。

+0

您的網站實際上並未返回HTTP 504網關超時,因爲錯誤本身意味着url請求的資源沒有及時響應。在你的情況下,可能是因爲應用程序池被關閉了,新的還沒有啓動。當應用程序池關閉時,它中的所有線程都會中止。這絕對會導致線程#2和#3上的HTTP 504 –

回答

12

iis中存在應用程序池關閉時間限制。假設這是60秒,並且在共享主機環境中存在應用程序池內存限制。您的應用程序池達到此限制,iis會通知應用程序池完成當前請求的所有工作。如果所有請求都在60秒前完成處理,則application_end將觸發,應用程序池將正常關閉。但是,如果60秒過去並且請求仍在處理中,則IIS會不安並殺死應用程序池。這次沒有application_end會觸發。同樣,不會觸發錯誤事件處理程序。

0

我那個正確觸發關機事件,這裏是在Global.asax中的簽名我的應用程序之一接過來一看。CS:

protected void Application_End(object sender, EventArgs e) 
{ 
    ApplicationShutdownReason shutdownReason = System.Web.Hosting.HostingEnvironment.ShutdownReason; 
    // Write to log 
} 

我注意到的唯一區別是,你的「Application_End」和「的Application_Error」的方法沒有「保護」調節劑。我已經看到很多情況,反思不能與私人成員一起工作,所以可能會發揮作用。

另外,請嘗試在本地/ dev應用程序池上將idle timeout設置爲低(如1分鐘),然後確保您的Application_End事件在本地觸發。

請注意,默認情況下,IIS應用程序池在沒有請求20分鐘後會回收,因此如果您的流量應用程序流量較低,則可能會觸及此情況。此外,某些共享主機提供商將此「空閒超時」值更改爲更低以節省資源。

+1

謝謝,但正如我所說的,我們正在爲其他類型的關閉獲取Application_End事件,「我知道他們正在工作,因爲有觸摸web.config或/ bin文件「。可愛的圖片btw :) – Laramie

+1

@拉拉米,對不起,我誤解了。你有沒有嘗試將你的開發環境[虛擬內存限制](http://technet.microsoft.com/en-us/library/cc753179(v = ws.10).aspx)設置爲非常低的值,以查看是否可以重現您在共享環境中看到的行爲? –

+0

我們正在接下來的工作,以便我們可以跟蹤內存使用情況。與此同時,我們一直在優化並暫時控制它。我不認爲在這裏會有一個簡單的答案,但我會很高興得到一個! – Laramie

0

不確定您使用的是哪個版本的IIS,但是在IIS7.5上有一堆應用程序池回收事件日誌設置,可讓您記錄應用程序池回收的原因。

在IIS中轉到應用程序池並轉到相關應用程序池的高級設置。回到Recycling並且有子菜單叫做「Generate Recycle Event Log Entry」。