在IIS7中以编程方式回收应用程序池的问题

时间:2011-02-22 18:39:55

标签: c# iis-7

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

默认情况下,IIS有一个90秒的“关闭时间限制”,在它终止任何仍在运行的线程之前等待90秒,所以我会调用ApplicationPool.Stop(),直到IIS终止它需要90秒应用程序池,在它的状态将被停止之前,我可以告诉它重新开始。任何试图使用该应用程序池命中任何应用程序的东西都会在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错误?

2 个答案:

答案 0 :(得分:7)

John Koerner的回答肯定有助于我指出正确的方向。使用Recycle会删除503错误。诀窍是如何杀死无限循环。

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

  1. 创建ServerManager对象
  2. 循环访问ServerManager对象上的ApplicationPools,直到找到您关心的appPool。提示:ApplicationPools.First(p =&gt; p.Name ==“DefaultAppPool”)是一个有用的功能
  3. 更新ApplicationPool.ProcessModel.ShutdownTimeLimit
  4. 在ServerManager对象上调用CommitChanges()。 注意:您提交更改的ServerManager对象必须是您用于获取ApplicationPool对象的对象,您对其进行了更改。你不能只做新的ServerManger()。CommitChanges();
  5. 睡眠一秒,以便在IIS中读取配置值。此时,您应该在IIS中的ApplicationPool上看到值更改
  6. 在ApplicationPool上调用Recycle或Stop
  7. 在回收ApplicationPool时,IIS有点奇怪,因为新的w3wp.exe ApplicationPool进程将立即启动,但旧的应用程序池将等待ApplicationPool.ProcessModel.ShutdownTimeLimit中的秒数关闭。然后它会将仍在运行的任何内容移动到新进程。但是如果你再次回收它,它将杀死无限循环(在ShutdownTimeLimit中等待适当的时间之后)。

    所以总结一下,正确地提交你的更改,等待它们生效,然后执行你的回收,如果你有一个你想要杀死的无限循环,那就再做一次。

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

答案 1 :(得分:2)

要在应用池上重新启动,您可以使用Recycle方法。这可能不会缓解90秒的问题。您可以使用Recycling对象中的某些内容来调整超时。