【问题标题】:Issues Programatically Recycling Application Pools in IIS7在 IIS7 中以编程方式回收应用程序池的问题
【发布时间】:2011-07-02 05:29:11
【问题描述】:

我创建了一个 C# 应用程序来回收 IIS 中的所有应用程序池,一次一个,使用 Microsoft.Web.Administration.ApplicationPool 类。 ApplicationPool 上没有重新启动应用程序池的方法(如果我错了,请纠正我),所以我认为您只需要停止,然后再启动。这在大多数情况下运行良好,直到我们开始在应用程序池中获取一些陷入无限循环的线程。

默认情况下,IIS 有一个 90 秒的“关闭时间限制”,它在终止任何仍在运行的线程之前等待 90 秒,所以我会调用 ApplicationPool.Stop(),它需要 90 秒直到 IIS 终止应用程序池,在它的状态停止之前,我可以告诉它重新开始。任何试图攻击任何使用该应用程序池的应用程序的东西,都会在这 90 秒内收到 503 错误响应,直到我可以再次启动该池为止。

我决定尝试以编程方式将“关闭时间限制”更改为 5 秒,以减少出现 503 错误的应用程序数量,但 IIS 在终止应用程序池之前仍在等待 90 秒。以下是我关闭应用程序池的功能:

private void StopAppPool(ApplicationPool applicationPool)
{
    ObjectState state = applicationPool.State;
    TimeSpan previousShutdownTimeLimit = applicationPool.ProcessModel.ShutdownTimeLimit;
    applicationPool.ProcessModel.ShutdownTimeLimit = new TimeSpan(0, 0, 5);
    switch (state)
    {
        case ObjectState.Started:
            applicationPool.Stop();
            WL("Application Pool {0}'s state has gone from {1} to {2}", applicationPool.Name, state, applicationPool.State);
            break;
        case ObjectState.Starting:
        case ObjectState.Unknown:
            for (int i = 0; i < 180; i++)
            {
                WL("Application Pool {0}'s state is {1}.  Waiting for state to become Started", applicationPool.Name, state);
                Thread.Sleep(500);
                state = applicationPool.State;
                if (applicationPool.State == ObjectState.Started) { break; }
            }
            if (state == ObjectState.Started)
            {
                applicationPool.Start();
                WL("Application Pool {0}'s state has gone from {1} to {2}", applicationPool.Name, state, applicationPool.State);
            }
            else
            {
                WL("Error starting Application Pool {0}: Application Pool never stopped", applicationPool.Name);
            }

            break;
        case ObjectState.Stopped:
        case ObjectState.Stopping:
            WL("Application Pool {0} was already in a {1} state and has not been modified", applicationPool.Name, state);
            break;
        default:
            WL("Error stopping Application Pool {0}: Unexpected ObjectState \"{1}\"", applicationPool.Name, state);
            break;
    }

    state = applicationPool.State;
    for (int i = 0; i < 180 && state != ObjectState.Stopped; i++)
    {
        WL("Application Pool {0}'s state is {1}.  Waiting for state to become Stopped", applicationPool.Name, state);
        Thread.Sleep(500);
        state = applicationPool.State;
    }
    applicationPool.ProcessModel.ShutdownTimeLimit = previousShutdownTimeLimit;
}    

为什么 ApplicationPool.ProcessModel.ShutdownTimeLimit 似乎不会影响 IIS 实际终止应用程序池所需的时间?在我尝试回收应用程序池时,是否有任何方法可以防止其他应用程序收到 503 错误?

【问题讨论】:

  • 你可能不想听到这个,但你到底为什么要回收应用程序池?

标签: c# iis-7


【解决方案1】:

John Koerner 的回答无疑帮助我指明了正确的方向。使用 Recycle 可消除 503 错误。诀窍是如何终止无限循环。

为了让 Recycle the App Pool 终止进程并遵守 ApplicationPool.ProcessModel.ShutdownTimeLimit 属性,您必须执行以下步骤:

  1. 创建一个 ServerManager 对象
  2. 遍历 ServerManager 对象上的 ApplicationPools,直到找到您关心的 appPool。提示:ApplicationPools.First(p => p.Name == "DefaultAppPool" ) 是一个有用的函数
  3. 更新 ApplicationPool.ProcessModel.ShutdownTimeLimit
  4. 在您的 ServerManager 对象上调用 CommitChanges()。 注意:您提交更改的 ServerManager 对象必须是您用来获取 ApplicationPool 对象的对象,您对其进行了更改。你不能只做 new ServerManger().CommitChanges();
  5. 请稍等片刻,以便在 IIS 中读取配置值。此时,您应该会看到 IIS 中 ApplicationPool 上的值发生变化
  6. 在您的应用程序池上调用回收或停止

在回收ApplicationPool时,IIS有点奇怪,一个新的w3wp.exe ApplicationPool进程会立即启动,而旧的应用程序池会等待ApplicationPool.ProcessModel.ShutdownTimeLimit中的秒数关闭。然后它会将仍在运行的任何内容移至新进程。但是如果你再次回收它,它会终止无限循环(在它等待 ShutdownTimeLimit 中的适当时间之后)。

总而言之,正确提交您的更改,等待它们生效,然后执行您的回收,如果您想杀死一个无限循环,请再次执行此操作。

我已经在我的博客上发布了源代码和最终的可执行文件here

【讨论】:

  • 当 IIS 中发生 appPool 回收时,它会创建一个新进程,并将所有新请求路由到新进程。它使旧进程保持运行,以便在关闭它之前可以完成当前正在运行的任何请求。它这样做是为了确保所有请求都得到处理,并且没有请求被放弃。
  • @ulty4life 是的,但实际上将其回收两次会杀死它。这就像它跟踪请求在 IIS 进程之间传输的次数,如果不止一次,它会终止它。
  • 干得好,我正在寻找与此类似的代码,您在解释过程中做得很好。
【解决方案2】:

要重新启动应用程序池,您可以使用Recycle 方法。不过,这可能不会缓解 90 秒的问题。 Recycling 对象中可能有一些东西可以用来调整超时。

【讨论】:

  • 把这个算作白痴。我一直在寻找重启,而不是回收!但是 Recycle 仍然没有更新状态,并且更改 ShutdownTimeLimit 似乎没有任何作用。
  • 当您更改 ShutdownTimeLimit 时,您可能还必须在 ServerManager 对象上调用 CommitChanges:msdn.microsoft.com/en-us/library/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-04
  • 1970-01-01
  • 2011-08-22
  • 1970-01-01
相关资源
最近更新 更多