asp.net - Application_End 是否应该触发自动应用程序池回收?

标签 asp.net iis memory-management

我已阅读 this , this , thisthis加上十几个其他帖子/博客。

我在共享主机中有一个经常回收的 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 STARTING”条目,但都没有 Application_OnEnd , Application_End ,也不是 Application_Error在这些自发重启期间被解雇。我知道他们正在工作,因为有用于接触 web.config 或/bin 文件的条目。我们还进行了内存过载测试,可以触发 OutOfMemoryException被捕获在 Application_Error .

我们正在尝试确定虚拟内存限制是否导致回收。我们添加了 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 Memory Profiler 相同,但似乎无法找到罪魁祸首。我们还使用 dev 中附加的调试器运行它,以检查可能导致应用程序中止的衍生线程中未捕获的异常。

我的问题是这些:
  • 如何有效监控共享主机中的内存使用情况,以在应用程序回收之前了解我的应用程序消耗了多少?
  • 为什么不调用 global.asax 中的 Application_[End/OnEnd/Error] 处理程序?
  • 我还能如何确定导致这些回收的原因?

  • 谢谢。

    编辑:基于@Jani Hyytiäinen 的回答

    设想:
    线程#1 开始,然后是线程#2。线程 #1 达到内存限制但继续处理。线程#3 开始。线程 #1 完成,但 #2 在 #1 达到内存限制后处理超过 60 秒。

    池然后不雅地中止? #2 和 #3 会收到什么 http 响应(这些是 AJAX 调用,但我在 Fiddler 中收到 504 错误)?
    对 #3 的请求是否被接受,还是只是排队直到新池启动?
    有没有办法知道内存限制已达到或即将达到?

    欢迎任何策略。

    最佳答案

    iis 中有应用程序池关闭时间限制。假设它是 60 秒,并且在共享托管环境中存在应用程序池内存限制。您的应用程序池达到此限制,iis 告诉应用程序池完成当前请求的所有工作。如果所有请求在 60 秒之前完成处理,application_end 将触发,应用程序池将正常关闭。但是,如果 60 秒过去了并且请求仍在处理中,IIS 会感到不安并杀死应用程序池。这次没有 application_end 会触发。同样,不会触发任何错误事件处理程序。

    关于asp.net - Application_End 是否应该触发自动应用程序池回收?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13388649/

    相关文章:

    本地 (Windows) 和 VPS (Fedora) 上的 PHP 内存使用差异

    c# - Razor View 中的简写 If without else (ASP.NET MVC4)

    c# - 在 Asp.NET 中使用 javascript

    iis - 无法在 Windows 10 预览版的 Microsoft Edge(Project Spartan)中打开 localhost

    ios - 我们如何在 ARC 中显式调用垃圾收集器?还有一种方法可以决定何时释放 ARC 中的内存?

    android - 在组件和应用程序之间传递数据

    asp.net - Visual Studio 项目恢复旧版本

    javascript - 在第一个页面加载时运行 javascript

    asp.net - IIS URL 重写 : Enforce canonical hostname & HTTP to HTTPS redirect

    web.config IIS 中的 PHP(或其他)CGI 配置