Иметь веб-приложение ASP.net, которое отлично работает в течение нескольких дней, но затем случайным образом выдает исключение из строки подключения к базе данных, и в результате в таблице отображаются 0 записей (их должно быть сотни). Я потратил много недель на отладку, память в порядке, база данных существует, и она исправлена с помощью всего, что может привести к перезагрузке приложения. Требуется много дней ожидания, чтобы даже воспроизвести.
Поэтому я подумал, поскольку знаю, что никогда не должно быть 0 записей, как я могу заставить пул приложений, выполняющих веб-приложение, перезапускаться (когда я получаю это исключение из базы данных или 0 записей). По крайней мере, так веб-сайт будет работать для следующего пользователя, и мне не нужно его перезапускать вручную.
Привет в этой статье вы можете найти соответствующий код для перезапуска пула приложений с Asp.net
Перезапустите пул приложений IIS со страницы ASP.NET
using System;
using System.Web;
using System.Web.UI;
using System.Management;
using System.DirectoryServices;
using System.Web.UI.WebControls;
public partial class iis : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(System.Environment.MachineName);
status();
}
protected void status()
{
string appPoolName = "dev.somesite.com";
string appPoolPath = @"IIS://" + System.Environment.MachineName + "/W3SVC/AppPools/" + appPoolName;
int intStatus = 0;
try
{
DirectoryEntry w3svc = new DirectoryEntry(appPoolPath);
intStatus = (int)w3svc.InvokeGet("AppPoolState");
switch (intStatus)
{
case 2:
lblStatus.Text = "Running";
break;
case 4:
lblStatus.Text = "Stopped";
break;
default:
lblStatus.Text = "Unknown";
break;
}
}
catch (Exception ex)
{
Response.Write(ex.ToString());
}
}
protected void stopAppPool(object sender, EventArgs e)
{
Button btn = (Button)sender;
string appPoolName = btn.CommandArgument;
string appPoolPath = @"IIS://" + System.Environment.MachineName + "/W3SVC/AppPools/" + appPoolName;
try
{
DirectoryEntry w3svc = new DirectoryEntry(appPoolPath);
w3svc.Invoke("Stop", null);
status();
}
catch (Exception ex)
{
Response.Write(ex.ToString());
}
}
protected void startAppPool(object sender, EventArgs e)
{
Button btn = (Button)sender;
string appPoolName = btn.CommandArgument;
string appPoolPath = @"IIS://" + System.Environment.MachineName + "/W3SVC/AppPools/" + appPoolName;
try
{
DirectoryEntry w3svc = new DirectoryEntry(appPoolPath);
w3svc.Invoke("Start", null);
status();
}
catch (Exception ex)
{
Response.Write(ex.ToString());
}
}
}
Я никогда не чувствовал себя полностью комфортно с этим решением из-за сложности, а также из-за того, что требования безопасности неясны (и если для этого вам нужно предоставить права пользователю приложения, это не только еще один шаг настройки, но и безопасность). риск, и кажется, что предоставление пользователю приложения прав на беспорядочную переработку пула приложений, особенно по сети, может быть использовано при атаке DOS).
В моей ограниченной ситуации, когда я обнаружил критические условия, которые я смог разрешить с помощью перезапуска и обнаружить во время выполнения, но еще не смог предотвратить более приемлемые изменения кода, и после долгих исследований я прошел через несколько других решений (ОК - хаки ), чтобы сделать это. 1. Создайте необработанное исключение для вновь порожденной нити, 2. Environment.Exit()
и 3 System.Web.HttpRuntime.UnloadAppDomain()
.. Они имеют довольно неприятный побочный эффект - завершение всех выполняющихся запросов, что, по общему признанию, является ужасным взломом, но допустимо в некоторых случаях (например, когда обнаруженное условие препятствует надлежащей обработке подавляющего большинства запросов в любом случае).
Отвращение к этому взлому оставалось со мной в течение многих лет, пока я недавно не наткнулся на этот маленький драгоценный камень, который намного проще и WMI
полностью избегает :
System.Web.Hosting.HostingEnvironment.InitiateShutdown();
Мое тестирование показало, что оно делает именно то , что мне было нужно, и я верю, что вы тоже этого хотели. Согласно документации, он существует с тех пор .NET 2.0
, но я никогда не сталкивался с этим в своих исследованиях, пока пару дней назад.
HttpRuntime.UnloadAppDomain();
, не могли бы вы объяснить, чем отличается ваше предложение? HttpRuntime.UnloadAppDomain();
прервет любые запросы в процессе. InitiateShutdown
отклоняет новые запросы, но завершает любые, которые уже выполняются.