Как узнать, почему пул приложений IIS перерабатывается

Задний план:

Я развернул приложение ASP.NET MVC 3, которое работает на моем компьютере, на общем хостинге Provider, и я обнаружил некоторые проблемы, которые, по-видимому, связаны с перезапуском пула приложений. Хост настроил перезапуск в любом из следующих случаев:

  • Использование памяти превышает 200 МБ
  • Использование ЦП превышает 75% (предположительно в течение длительного периода)
  • 20 минут простоя

На моей машине для разработки ограничения более мягкие, поэтому я не видел такой утилизации во время разработки. У меня нет доступа администратора к ящику общего хостинга (по понятным причинам), поэтому я не могу прочитать журнал событий, чтобы понять, почему происходит эта переработка.

Вопрос:

Есть ли способ узнать, почему мое приложение было переработано (например, в Application_End), чтобы я мог зарегистрировать его, чтобы облегчить отладку?


person Drew Noakes    schedule 26.03.2011    source источник


Ответы (4)


Без доступа к журналам событий (потому что вы находитесь в среде общего хостинга) большая часть информации, которую вы собираетесь получить, - это событие Application_End и запрос HttpRuntime (через отражение) для значений одного или двух частных членов, которые к сожалению, не раскрываются публично.

Для этого добавьте в событие Application_End следующий код:

BindingFlags staticFlags = 
    BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetField;
BindingFlags instanceFlags = 
    BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField;

HttpRuntime runtime = (HttpRuntime)typeof(System.Web.HttpRuntime)
                        .InvokeMember("_theRuntime", staticFlags, null, null, null);
if(runtime != null) 
{
    string shutDownMessage = (string)runtime.GetType()
         .InvokeMember("_shutDownMessage", instanceFlags, null, runtime, null);

    string shutDownStack = (string)runtime.GetType()
         .InvokeMember("_shutDownStack", instanceFlags, null, runtime, null);

    // Log shutDownMessage & shutDownStack somewhere
}

Если я закрываю или перезагружаю пул приложений своего приложения, я вижу следующее:

HostingEnvironment initiated shutdown
HostingEnvironment caused shutdown -    
   at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
   at System.Environment.get_StackTrace()
   at System.Web.Hosting.HostingEnvironment.InitiateShutdownInternal()
   at System.Web.Hosting.HostingEnvironment.InitiateShutdownWithoutDemand()
   at System.Web.Hosting.PipelineRuntime.StopProcessing()

Это, вероятно, почти так же хорошо, как и получается.

Обновление:

Я не мог вспомнить, где я нашел этот код, но Дрю услужливо напомнил мне, что это из сообщения в блоге Скотта Гатри.

Есть некоторые другие частные члены, которые могут быть полезны, например:

private ApplicationShutdownReason _shutdownReason;

Вы можете изучить эти поля в .NET Reflector (если у вас все еще есть копия, которая не подверглась бомбардировке с часовым механизмом) или в одной из альтернатив (Альтернативы Reflector с открытым исходным кодом?).

person Kev    schedule 26.03.2011
comment
Вы нашли это в блоге ScottGu? Я пробовал этот подход перед тем, как опубликовать вопрос, но он не дает много полезных данных. Я получаю сообщение Завершение работы по инициативе HostingEnvironment, что не помогает мне понять, что мне нужно сделать, чтобы удовлетворить требования среды размещения. - person Drew Noakes; 26.03.2011
comment
Вы можете получить доступ к этим данным, вообще говоря, через свойство System.Web.Hosting.HostingEnvironment.ShutdownReason (это перечисление). - person Drew Noakes; 26.03.2011
comment
@drew - а я этого не знал. - person Kev; 26.03.2011
comment
Без проблем. Кстати, это Скотт Гатри, а не Гензельман. Ссылка на его сообщение в блоге была в моем первом комментарии: веб-журналы. asp.net/scottgu/archive/2005/12/14/433194.aspx - person Drew Noakes; 26.03.2011
comment
@drew - сегодня я полный # провал :) - person Kev; 26.03.2011
comment
Действительно, есть подробный комментарий для этого перечисления _shutdownReason, который можно увидеть с помощью отражателя. Вот фрагмент, чтобы получить это значение перечисления: string shutDownReason = runtime.GetType().GetField("_shutdownReason", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField) .GetValue(runtime).ToString(); - person BornToCode; 26.05.2017

Исследования - 1

Сначала я пробовал использовать System.Web.ProcessModelInfo.GetCurrentProcessInfo() и System.Web.ProcessModelInfo.GetHistory(int). Результаты этих методов возвращают такую ​​информацию, как PID, время начала, возраст, статус и пиковое использование памяти. К сожалению, в моей среде хостинга они были недоступны:

HttpException 0x80004005 - метрики процесса доступны только при включенной модели процесса ASP.NET. При работе в версиях IIS 6 или новее в режиме изоляции рабочих процессов эта функция не поддерживается.

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

Исследования - 2

Свойство System.Web.Hosting.HostingEnvironment.ShutdownReason - это перечисление с множеством значений, но, к сожалению, все случаи, которые я описываю в своем вопросе, объединены в одно значение перечисления:

ApplicationShutdownReason.HostingEnvironment: среда размещения завершила работу домена приложения.

Исследования - 3

ScottGu опубликовал в своем блоге ( тот же код Кев опубликовал ), который использует отражение для доступа к внутреннему состоянию HttpApplication. К сожалению, в этом случае он сообщает только те же детали, что и # 2 выше:

_shutDownMessage =
  HostingEnvironment initiated shutdown
  HostingEnvironment caused shutdown

_shutDownStack =
  at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
  at System.Environment.get_StackTrace()
  at System.Web.Hosting.HostingEnvironment.InitiateShutdownInternal()
  at System.Web.Hosting.HostingEnvironment.InitiateShutdownWithoutDemand()
  at System.Web.Hosting.PipelineRuntime.StopProcessing()
person Drew Noakes    schedule 26.03.2011
comment
Я не понимаю. Вы описали то, что было недоступно в вашей среде, затем перечисление, которое не помогло, и отраженное свойство, которое не помогло. Так что же было последней причиной перезапуска вашего приложения? - person anon; 04.03.2015

Это действительно поздний ответ, но я надеюсь, что он может дать дополнительную информацию для тех, у кого есть похожие проблемы (IIS 7.x или выше).

1. Определение момента начала завершения работы пула приложений - следующий код можно использовать для определения момента начала завершения работы пула приложений. Фактическое завершение работы происходит в течение максимального предела выключения (секунд, по умолчанию 90) после этого события.

public class ApplicationPoolService : IApplicationPoolService
{
    public bool IsShuttingDown()
    {
        return System.Web.Hosting.HostingEnvironment.ShutdownReason != ApplicationShutdownReason.None;
    }

    public ApplicationShutdownReason GetShutdownReason()
    {
        return System.Web.Hosting.HostingEnvironment.ShutdownReason;
    }
}

public class HostingEnvironmentRegisteredObject : IRegisteredObject
{
    public void Stop(bool immediate)
    {
        // second call is done when the Stop is imminent 
        if (immediate)
            return;

        var reason = appPoolService.GetShutdownReason().ToString();
        logger.Log(LogLevel.Info, $"HostingEnvironmentRegisteredObject.stop called with shutdown reason {reason}");
    }
}

// this code should be placed in global.asax.cs
protected void Application_Start()
{
    HostingEnvironment.RegisterObject(new HostingEnvironmentRegisteredObject());
}

Это помогает найти общую причину и точное время срабатывания. В вашем случае, я думаю, HostingEnvironment - это значение. К сожалению, основная причина не уникальна. Это может быть периодическая переработка, переработка из-за ограничения памяти (наиболее вероятная причина в вопросе OP), переработка из-за фиксированного часа и т. Д.

2. Поиск точной причины - один из способов узнать точную причину - найти ее в журнале событий. Если это недоступно, его можно запросить у хостинг-провайдера, указав следующие данные, чтобы сузить область поиска.

  • Точное время начала отключения
  • Event log filter:
    • Event sources = WAS
    • Уровень события = Информация
    • В журнале = настраиваемый диапазон, включая точное время выключения +/- 1 минута или около того

Журнал событий должен возвращать более релевантную информацию, подобную приведенной ниже:

Рабочий процесс с идентификатором процесса «xxx», обслуживающий пул приложений «xxx», запросил перезапуск, поскольку он достиг запланированного времени перезапуска.


Рабочий процесс с идентификатором процесса «xxx», обслуживающий пул приложений «xxx», запросил перезапуск, поскольку достиг предела виртуальной памяти.

person Alexei - check Codidact    schedule 26.01.2017

Ниже приведен хороший код из https://mitchelsellers.com/blog/article/logging-asp-net-application-restarts

//  obtain the shutdown reason
System.Web.ApplicationShutdownReason shutdownReason = System.Web.Hosting.HostingEnvironment.ShutdownReason;
string shutdownDetail = "";

//Evaluate which option caused the error
switch (shutdownReason)
{
    case ApplicationShutdownReason.BinDirChangeOrDirectoryRename:
        shutdownDetail = "A change was made to the bin directory or the directory was renamed";
        break;
    case ApplicationShutdownReason.BrowsersDirChangeOrDirectoryRename:
        shutdownDetail = "A change was made to the App_browsers folder or the files contained in it";
        break;
    case ApplicationShutdownReason.ChangeInGlobalAsax:
        shutdownDetail = "A change was made in the global.asax file";
        break;
    case ApplicationShutdownReason.ChangeInSecurityPolicyFile:
        shutdownDetail = "A change was made in the code access security policy file";
        break;
    case ApplicationShutdownReason.CodeDirChangeOrDirectoryRename:
        shutdownDetail = "A change was made in the App_Code folder or the files contained in it";
        break;
    case ApplicationShutdownReason.ConfigurationChange:
        shutdownDetail = "A change was made to the application level configuration";
        break;
    case ApplicationShutdownReason.HostingEnvironment:
        shutdownDetail = "The hosting environment shut down the application";
        break;
    case ApplicationShutdownReason.HttpRuntimeClose:
        shutdownDetail = "A call to Close() was requested";
        break;
    case ApplicationShutdownReason.IdleTimeout:
        shutdownDetail = "The idle time limit was reached";
        break;
    case ApplicationShutdownReason.InitializationError:
        shutdownDetail = "An error in the initialization of the AppDomain";
        break;
    case ApplicationShutdownReason.MaxRecompilationsReached:
        shutdownDetail = "The maximum number of dynamic recompiles of a resource limit was reached";
        break;
    case ApplicationShutdownReason.PhysicalApplicationPathChanged:
        shutdownDetail = "A change was made to the physical path to the application";
        break;
    case ApplicationShutdownReason.ResourcesDirChangeOrDirectoryRename:
        shutdownDetail = "A change was made to the App_GlobalResources foldr or the files contained within it";
        break;
    case ApplicationShutdownReason.UnloadAppDomainCalled:
        shutdownDetail = "A call to UnloadAppDomain() was completed";
        break;
    default:
        shutdownDetail = "Unknown shutdown reason";
        break;
}
person KMR    schedule 22.03.2016