Проблемы программной переработки пулов приложений в IIS7 - PullRequest
2 голосов
/ 22 февраля 2011

Я создал приложение C # для перезапуска всех пулов приложений в IIS, по одному, используя класс Microsoft.Web.Administration.ApplicationPool. В ApplicationPool нет способа перезапустить пул приложений (пожалуйста, исправьте меня, если я ошибаюсь), поэтому я решил, что вам просто нужно сделать остановку, а затем начать. Это работало нормально по большей части, пока мы не начали получать некоторые потоки в пуле приложений, которые застряли в бесконечном цикле.

По умолчанию IIS имеет 90-секундный «предел времени выключения», где он ждет 90 секунд, прежде чем завершит работу всех потоков, которые еще работают, поэтому я вызову ApplicationPool.Stop (), и потребуется 90 секунд, пока IIS не завершит пул приложений, прежде чем его состояние будет остановлено, и я мог сказать ему, чтобы начать снова. Все, что попытается поразить любые приложения, использующие этот пул приложений, получит ответ 503 об ошибке в течение этих 90 секунд, пока я не смогу снова запустить пул.

Я решил попробовать программно изменить «Время отключения» на 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 ]

7 голосов
/ 24 февраля 2011

Ответ Джона Кернера определенно помог направить меня в правильном направлении. Использование Recycle удаляет 503 ошибки. Хитрость заключалась в том, как убить бесконечный цикл.

Вот шаги, которые вы должны предпринять, чтобы Recycle App Pool завершил процесс и подчинялся свойству ApplicationPool.ProcessModel.ShutdownTimeLimit:

  1. Создать объект ServerManager
  2. Перебирайте ApplicationPools в объекте ServerManager, пока не найдете нужный вам appPool. Совет: ApplicationPools.First (p => p.Name == "DefaultAppPool") является полезной функцией
  3. Обновление ApplicationPool.ProcessModel.ShutdownTimeLimit
  4. Вызовите CommitChanges () для вашего объекта ServerManager. ПРИМЕЧАНИЕ: Объект ServerManager, для которого вы фиксируете изменения, должен быть объектом, который вы использовали для получения объекта ApplicationPool, в который вы внесли изменения. Вы не можете просто сделать новый ServerManger (). CommitChanges ();
  5. Спите секунду, чтобы значение конфигурации было прочитано в IIS. На этом этапе вы должны увидеть изменение значения в ApplicationPool в IIS
  6. Вызовите Recycle или Stop на вашем ApplicationPool

При утилизации ApplicationPool IIS выглядит несколько странно, поскольку новый процесс ApplicationPool w3wp.exe запускается немедленно, но старый пул приложений будет ожидать количество секунд в ApplicationPool.ProcessModel.ShutdownTimeLimit для завершения работы. Затем он переместит все, что еще переходит, в новый процесс. Но если вы перезапустите его снова, он уничтожит бесконечный цикл (после того, как он подождет подходящее время в ShutdownTimeLimit).

Итак, чтобы подвести итог, правильно зафиксировать изменения, подождать, пока они вступят в силу, затем выполнить повторную обработку, а затем повторить, если у вас есть бесконечный цикл, который вы хотите убить.

Я разместил исходный код и окончательный исполняемый файл здесь в моем блоге.

2 голосов
/ 22 февраля 2011

Чтобы перезапустить пул приложений, вы можете использовать метод Recycle .Это, вероятно, не облегчит проблему 90 секунд, хотя.В объекте Recycling может быть что-то, с чем можно поиграть, чтобы скорректировать время ожидания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...