C# IIS7中程序化回收应用程序池的问题

C# IIS7中程序化回收应用程序池的问题,c#,iis-7,C#,Iis 7,我使用Microsoft.Web.Administration.ApplicationPool类创建了一个C#应用程序来回收IIS中的所有应用程序池,一次一个。ApplicationPool上没有重新启动应用程序池的方法(如果我错了,请纠正我),因此我认为您只需先停止,然后启动。这在大部分情况下都可以正常工作,直到我们开始在应用程序池中获得一些线程,这些线程被困在无限循环中 默认情况下,IIS有一个90秒的“关机时间限制”,在终止任何仍在运行的线程之前,它会等待90秒,因此我会调用Applica

我使用Microsoft.Web.Administration.ApplicationPool类创建了一个C#应用程序来回收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;
}    
private void stopppool(ApplicationPool ApplicationPool)
{
ObjectState状态=applicationPool.state;
TimeSpan previousShutdownTimeLimit=applicationPool.ProcessModel.ShutdownTimeLimit;
applicationPool.ProcessModel.ShutdownTimeLimit=新的时间跨度(0,0,5);
开关(状态)
{
案例ObjectState。已启动:
applicationPool.Stop();
WL(“应用程序池{0}的状态已从{1}变为{2}”,applicationPool.Name,state,applicationPool.state);
打破
案例ObjectState。正在启动:
案例ObjectState。未知:
对于(int i=0;i<180;i++)
{
WL(“应用程序池{0}的状态为{1}。正在等待状态变为启动”,applicationPool.Name,state);
睡眠(500);
state=applicationPool.state;
如果(applicationPool.State==ObjectState.Started){break;}
}
if(state==ObjectState.Started)
{
applicationPool.Start();
WL(“应用程序池{0}的状态已从{1}变为{2}”,applicationPool.Name,state,applicationPool.state);
}
其他的
{
WL(“启动应用程序池{0}时出错:应用程序池从未停止”,applicationPool.Name);
}
打破
案例对象状态。已停止:
案例ObjectState。正在停止:
WL(“应用程序池{0}已处于{1}状态,尚未修改”,applicationPool.Name,state);
打破
违约:
WL(“停止应用程序池{0}时出错:意外的ObjectState\“{1}\”,applicationPool.Name,state);
打破
}
state=applicationPool.state;
for(int i=0;i<180&&state!=ObjectState.Stopped;i++)
{
WL(“应用程序池{0}的状态为{1}。正在等待状态变为停止”,applicationPool.Name,state);
睡眠(500);
state=applicationPool.state;
}
applicationPool.ProcessModel.ShutdownTimeLimit=previousShutdownTimeLimit;
}    

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

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

约翰·科纳的回答肯定为我指明了正确的方向。使用Recycle可删除503错误。诀窍是如何杀死无限循环

以下是您必须采取的步骤,以便回收应用程序池以终止进程并遵守ApplicationPool.ProcessModel.ShutdownTimeLimit属性:

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

    总之,正确地提交更改,等待更改生效,然后执行循环,如果有一个无限循环要终止,请再次执行


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

    把这一条算作白痴。我一直在寻找重新启动,而不是回收!但是循环仍然不会更新状态,更改ShutdownTimeLimit似乎没有任何作用。更改ShutdownTimeLimit时,可能还必须调用ServerManager对象上的CommitChanges: