检测ASP.NET应用程序何时重新启动

11

我想检测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 事件只会触发一次。

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


6
您能否使用 Application_Start 来代替呢?我猜一些事件,比如关机或断电,可能不会让您知道何时调用了 Application_End。 - Pit Digger
1
你确定在修改了web.config文件后访问了应用程序中的页面,以便它结束并重新启动吗?因为如果它没有重新启动,我可以看到这会阻止Application_End在此之后触发。 - StriplingWarrior
3个回答

4
以下可能有点儿hack,但你可以使用应用程序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的替代方法。 - Kelsey
1
只有 Application_Start 总是会被调用,而 Application_End 可能不会 - 例如在应用程序回收时。 - TheCodeKing
Application_End方法在回收时也会被调用。不确定为什么您认为它不会被调用。 - Triynko

3
以下是问题的良好答案,它们提供在以下堆栈溢出问题中:如何检测当前应用程序池是否正在关闭 要跟踪应用程序池回收,您需要实现IRegisteredObject接口,调用ApplicationManager.CreateObject创建对象的实例,并在应用程序启动期间使用HostingEnvironment.RegisterObject进行注册。
当带有false参数的IRegisteredObject.Stop(bool)实现被调用时,这是通知应用程序域正在关闭并且对象应该使用HostingEnvironment.UnregisterObject取消注册(类似于全局dispose)的通知。
因此,使用此事件,您可以跟踪应用程序池何时被回收。

0
为什么不这样做呢?调整计时器作业的频率,以提高确定应用程序池何时回收的准确性。
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();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接