ТЛ; др
После довольно обширного тестирования и сбора соответствующих источников, чтобы попытаться решить проблему, я думаю, что минимальное решение может быть (не проверено), чтобы добавить этот код в global.asax:
protected void Application_End()
{
...
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://web_domain.tld");
using (HttpWebResponse response = (HttpWebResponse)
request.GetResponse())
{
}
...
}
Во время написания поста это использовалось для эффективного поддержания сайта, над которым я работал, «всегда активным» - с соединением установки Idle Time-out (minutes)
в IIS в 0, как упоминалось в других ответах. Однако я думаю, что изменение Idle Time-out (minutes)
может не потребоваться (при условии, что событие Application_end
возникает, когда происходит переключение пула приложений в режим ожидания).
Как это работает (при условии, что это работает):
- В настройках пула приложений IIS есть 2 параметра, которые влияют на приостановку или завершение работы приложения. Один из них -
Idle Time-out (minutes)
, который по умолчанию равен 20 минутам, и когда указанное время истекает с момента последнего запроса , рабочий процесс приостанавливается или завершается. Когда приходит следующий запрос, рабочий процесс возобновляется или запускается снова, и возникает событие Application_start (и поэтому, если обработчик Application_start определен в global.asax, он выполняется). В случае проекта, над которым я работал, запуск Application_start занял около 17 секунд. Таким образом, если сайт был «оставлен в покое» в течение 21 минуты, а затем пришел новый запрос, то для отправки ответа потребовалось чуть более 17 секунд (Application_start + обработка страницы). Когда в течение 20 минут был отправлен другой запрос, ответ был отправлен значительно быстрее (возможно, менее 1 с), поскольку Application_start уже обработан.
Установка значения Idle Time-out (minutes)
в 0 приводит к тому, что рабочий процесс никогда не приостанавливается / не прекращается (по крайней мере, из-за простоя - может быть другая причина, описанная ниже).
- Помимо
Idle Time-out (minutes)
, в разделе Recycling
дополнительных настроек IIS есть также настройка Regular time interval (minutes)
. По умолчанию это 1740 минут (29 часов) и является обычной запланированной задачей, из-за которой пул приложений периодически перезагружается (период является фиксированным). Я понял, что это предотвращает накопление возможных утечек памяти, которые, если они есть, могут в конечном итоге привести к сбою сервера из-за перегрузки всей памяти. Эффект утилизации пула приложений заключается в том, что возникает событие Application_end. Однако после завершения приложения оно не запускается автоматически, поэтому событие Application_start не вызывается до тех пор, пока не поступит фактический запрос (что аналогично первому случаю). Таким образом, в случае вышеупомянутого веб-приложения, над которым я работал, снова потребовалось бы около 17 секунд для обработки первого запроса, поступившего после того, как произошла переработка. Изменение этого значения на 0 отключает рециркуляцию, но я полагаю, что не стоит полностью отключать рециркуляцию из-за возможности накопления утечек памяти с течением времени (что может быть даже вызвано ошибками в сторонних библиотеках). Я понимаю, что мнения расходятся относительно того, следует ли установить это значение на 0 или , а не и может со временем меняться.
Возможное решение (без изменения настроек IIS):
Если запросы отправляются достаточно часто, пул приложений может никогда не переключиться в режим ожидания. В случае повторного использования это также может привести к повторному запуску приложения. Это может быть достигнуто, например, с помощью стороннего сервиса, как описано в @ Rippo.
Предлагаемое решение:
Было замечено, что пул приложений recycling вызвал событие Application_end
. Предполагая, что он также поднимается при переключении пула приложений в Режим ожидания , может показаться достаточным создать запрос в обработчике событий Application_end
на веб-сайт, который в обоих случаях вызовет приложение, чтобы начать снова (вызывает событие Application_start). Код вверху ответа.