【问题标题】:Detecting when an ASP.NET application recycles检测 ASP.NET 应用程序何时回收
【发布时间】:2011-11-08 11:04:06
【问题描述】:

我正在尝试检测 ASP.NET 应用程序何时因 web.config 文件被修改或 IIS 应用程序池被手动回收而被回收。

一开始我认为 ASP.NET 的 Application_End 方法会起作用,并尝试了以下方法:

protected void Application_End(object sender, EventArgs e)
{
    File.AppendAllText("log.txt", DateTime.Now + "\n");
}

该文件是在第一次更改 web.config 文件时创建的,但随后的更改并未触发该事件。同样,在 IIS 中进行测试时,第一个手动应用程序池回收创建了文件,但后来的没有 - 就好像 Application_End 事件只触发一次。

我将如何检测每次池/应用程序回收?

【问题讨论】:

  • 你不能使用 Application_Start 吗?我猜某些事件(例如关机或断电)不会让您知道何时调用 Application_End。
  • 您是否确定在更改 web.config 文件后访问了应用程序中的页面,所以它结束然后重新开始?因为如果它不再启动,我可以看到阻止 Application_End 之后触发。

标签: c# asp.net iis application-pool


【解决方案1】:

以下内容可能有点小技巧,但您可以使用应用程序Cache 来解决。每次加载页面时,您都可以检查缓存中的特定键,如果该键不存在,那么您可以将其视为“回收”,然后添加该键。不是最好的方法,但可能只满足您的需要。

例如。在您的基本页面的Page_Load 或每个请求都会运行的某个地方,您可以执行以下操作:

if (HttpContext.Current.Cache["RecycleCheck"] != null)
{ 
    // Add flag to cache
    HttpContext.Current.Cache.Insert("RecycleCheck", "1", null,
        DateTime.UtcNow.AddDays(2),  // 2 days (most will recycle by then)
        System.Web.Caching.Cache.NoSlidingExpiration);

    // Do what you need because a recycle has happened
}

此方法不会在循环发生时将其拾取。它只会在回收后的第一个请求上识别回收。

Application_Start 将是执行此操作的最可靠的位置,但它与 hack 存在相同的问题,因为它发生在第一个请求的回收之后。

【讨论】:

  • @TheCodeKing 这不是我说(注意我回答的最后一行)Application_Start 将是最好的地方的原因。仅当由于某种原因有问题导致 Application_EndStart 无法触发时,这是一个 hacky 替代方案。
  • 只有Application_Start总是被调用,只有Application_End 可能不会 - 例如在应用回收时。
  • Application_End 也被 Recycle 调用。不知道你为什么建议它不会。
【解决方案2】:

以下堆栈溢出问题提供了这个问题的好答案:how to detect if the current application pool is winding up

要跟踪应用程序池回收,您需要实现 IRegisteredObject 接口,调用 ApplicationManager.CreateObject 以创建对象的实例,然后在应用程序启动期间将其注册到 HostingEnvironment.RegisterObject。

当使用 false 作为参数调用此对象的 IRegisteredObject.Stop(bool) 实现时,这是通知应用程序域正在关闭并且该对象应该通过调用取消注册(有点像全局处置)到 HostingEnvironment.UnregisterObject。

因此,使用此事件您可以跟踪应用程序池何时被回收。

【讨论】:

    【解决方案3】:

    你为什么不做这样的事情。调整计时器作业的频率,以提高确定 appPool 何时回收的准确性。

    private readonly Timer timer = new Timer();
    private DateTime start;
    private string logFile;
    
    void Application_Start(object sender, EventArgs e)
    {
      start= DateTime.Now;
      logFile = Server.MapPath(
                string.Concat("Log-",start.ToString("yyyyMMdd-HHmmss.fff"),".txt"));
    
      timer.Interval = 1000;
      timer.Elapsed += (s, ee) 
                => File.WriteAllText(logFile,
                string.Concat("App Start :", start, " Last Alive: ", DateTime.Now));
    
      timer.Start();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-12
      • 2015-12-14
      • 2011-08-22
      • 2014-05-02
      • 2020-05-23
      • 2013-08-15
      • 2012-05-10
      • 2020-01-21
      相关资源
      最近更新 更多