如何判断IIS应用程序池的回收原因

时间:2011-03-26 15:39:48

标签: asp.net iis iis-7 asp.net-mvc-3 application-pool

背景

我已经将在我的计算机上运行的ASP.NET MVC 3应用程序部署到shared hosting provider,并且发现了一些似乎与正在回收的应用程序池相关的问题。主机已配置在以下任何情况下进行回收:

  • 内存使用量超过200MB
  • CPU使用率超过75%(可能在一段持续时间内)
  • 20分钟的闲置时间

我的开发机器上的限制更加轻松,因此在开发过程中我没有看到这样的回收。我没有管理员访问共享主机盒(可以理解),所以我无法阅读事件日志,看看为什么会发生这种回收。

问题:

有没有办法可以找出我的应用程序被回收的原因(例如Application_End),以便我可以记录它来帮助调试?

4 个答案:

答案 0 :(得分:11)

无法访问事件日志(因为您处于共享托管环境中),您将获得的最多信息来自Application_End事件并询问HttpRuntime(通过反思) )一个或两个私人成员的价值,遗憾的是没有公开曝光。

为此,请将以下代码添加到Application_End事件中:

BindingFlags staticFlags = 
    BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetField;
BindingFlags instanceFlags = 
    BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField;

HttpRuntime runtime = (HttpRuntime)typeof(System.Web.HttpRuntime)
                        .InvokeMember("_theRuntime", staticFlags, null, null, null);
if(runtime != null) 
{
    string shutDownMessage = (string)runtime.GetType()
         .InvokeMember("_shutDownMessage", instanceFlags, null, runtime, null);

    string shutDownStack = (string)runtime.GetType()
         .InvokeMember("_shutDownStack", instanceFlags, null, runtime, null);

    // Log shutDownMessage & shutDownStack somewhere
}

如果我关闭或回收我的应用程序的应用程序池,我会看到以下内容:

HostingEnvironment initiated shutdown
HostingEnvironment caused shutdown -    
   at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
   at System.Environment.get_StackTrace()
   at System.Web.Hosting.HostingEnvironment.InitiateShutdownInternal()
   at System.Web.Hosting.HostingEnvironment.InitiateShutdownWithoutDemand()
   at System.Web.Hosting.PipelineRuntime.StopProcessing()

这可能和它一样好。

<强>更新

我不记得我在哪里找到了这段代码,但Drew提醒我这是来自Scott Guthrie博客文章。

还有一些其他私人成员可能很有用,例如:

private ApplicationShutdownReason _shutdownReason;

您可以在.NET Reflector中检查这些字段(如果您还有一个没有时间轰炸的副本)或其中一个备选方案(Open Source Alternatives to Reflector?)。

答案 1 :(得分:7)

研究 - 1

首先,我尝试使用System.Web.ProcessModelInfo.GetCurrentProcessInfo()System.Web.ProcessModelInfo.GetHistory(int)。这些方法的结果返回信息,例如PID,开始时间,年龄,状态和峰值内存使用情况。不幸的是,这些在我的托管环境中无法使用:

  

HttpException 0x80004005 - 仅当启用ASP.NET进程模型时,进程度量标准才可用。在工作进程隔离模式下运行IIS 6或更高版本时,不支持此功能。

这种方法可能适用于其他人,所以如果你处于这种情况,请试一试。

研究 - 2

属性System.Web.Hosting.HostingEnvironment.ShutdownReason是一个包含大量值的枚举,但不幸的是,我在问题中概述的所有案例都捆绑在一个枚举值中:

  

ApplicationShutdownReason.HostingEnvironment:托管环境关闭了应用程序域。

研究 - 3

ScottGu has an approach on his blog(代码Kev posted),它使用反射来访问HttpApplication的内部状态。不幸的是,在这种情况下,它只报告与上面#2相同的细节:

_shutDownMessage =
  HostingEnvironment initiated shutdown
  HostingEnvironment caused shutdown

_shutDownStack =
  at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
  at System.Environment.get_StackTrace()
  at System.Web.Hosting.HostingEnvironment.InitiateShutdownInternal()
  at System.Web.Hosting.HostingEnvironment.InitiateShutdownWithoutDemand()
  at System.Web.Hosting.PipelineRuntime.StopProcessing()

答案 2 :(得分:3)

以下是http://mitchelsellers.com/blogs/2007/03/15/logging-aspnet-application-restarts.aspx

的优秀代码
 inner join 
     REZNVOD01.dbo.TimeZoneVariation tzv on tzv.TimeZoneCode = s.TimeZoneCode 
                                         and tzv.EndUTC >= BookingDate
                                         and tzv.StartUTC <= BookingDate

答案 3 :(得分:3)

这是一个非常晚的答案,但我希望它可以为那些有类似问题(IIS 7.x或更高版本)的人提供额外的见解。

<强> 1。查找应用程序池何时开始关闭 - 以下代码可用于查找应用程序池何时开始关闭。在此事件发生后,实际关闭的最大关闭限制(秒,默认为90)。

public class ApplicationPoolService : IApplicationPoolService
{
    public bool IsShuttingDown()
    {
        return System.Web.Hosting.HostingEnvironment.ShutdownReason != ApplicationShutdownReason.None;
    }

    public ApplicationShutdownReason GetShutdownReason()
    {
        return System.Web.Hosting.HostingEnvironment.ShutdownReason;
    }
}

public class HostingEnvironmentRegisteredObject : IRegisteredObject
{
    public void Stop(bool immediate)
    {
        // second call is done when the Stop is imminent 
        if (immediate)
            return;

        var reason = appPoolService.GetShutdownReason().ToString();
        logger.Log(LogLevel.Info, $"HostingEnvironmentRegisteredObject.stop called with shutdown reason {reason}");
    }
}

// this code should be placed in global.asax.cs
protected void Application_Start()
{
    HostingEnvironment.RegisterObject(new HostingEnvironmentRegisteredObject());
}

这有助于找到一般原因以及确切触发的时间。在您的情况下,我认为HostingEnvironment是值。不幸的是,根本原因并不是唯一的。它可以是定期回收,由于内存限制而回收(OP问题中最可能的原因),由于固定时间等而回收。

<强> 2。找到确切原因 - 找出确切原因的一种方法是在EventLog中搜索它。如果无法访问,可以通过提供以下详细信息来向托管服务提供商请求缩小搜索范围。

  • 关闭启动的确切时间
  • 事件日志过滤器:
    • 活动来源= WAS
    • 活动级别=信息
    • 记录=自定义范围,包括准确的关机时间+/- 1分钟左右

事件日志应返回更多相关信息,如下所示:

  

进程ID为&#39; xxx&#39;的工作进程服务应用程序池   &#39; XXX&#39;已要求回收,因为它到达了它   预定的回收时间。


  

进程ID为&#39; xxx&#39;的工作进程服务应用程序池   &#39; XXX&#39;已请求回收,因为它已到达其虚拟内存   限制。