Почему мой пул приложений IIS7 завершает работу после исключения в DLL, вызванном с страницы ASP.NET?
Я прочитал сообщения Проблема закрытия пула приложений ASP.NET и IIS 7.5: проблема с пулом приложений но они не ответили на мой вопрос.
У меня есть страница ASP.NET С#, которая в коде-образе создает экземпляр класса из DLL, поставляемого через каталог BIN, а затем вызывает метод в этом экземпляре. Метод внутри DLL выбрасывает System.ArgumentException
из-за не существующего столбца в объекте DataRow
. Журнал событий показывает следующую ошибку:
Source: ASP.NET 2.0.50727.0
Application ID: /LM/W3SVC/1/ROOT/...
Process ID: 9476
Exception: System.ArgumentException
Message: Column 'someColumn' does not belong to table.
StrackTrace:
Вызывающий код на странице ASP.NET переносит вызов метода в общий try-catch
блок. Когда я запрашиваю страницу, это приведет к сбою соответствующего пула приложений моего экземпляра IIS, и мой веб-сайт больше не доступен (ошибка 503). Я вручную должен перезапустить пул приложений, и сайт снова работает.
Обновление
Как запрошено блок try catch
из кода ASP.NET позади:
try
{
SomeExternalClass someExternalClass = new SomeExternalClass();
someExternalClass.SomeMethod( someId );
}
catch( Exception ex )
{
// "smp" is an instance of "StatusMessagePanel", a control we use on all pages
// to show error information, basically a div container with an icon.
smp.ShowError( ex.Message );
}
Теперь мой вопрос в том, почему относительно простое исключение, такое как System.ArgumentException
, которое бросается при попытке получить доступ к не существующему столбцу DataRow
, приводит к сбою всего веб-сайта? Также не помогает общий шаблон try-catch
на странице ASP.NET, и это не должно стать причиной полного недопущения всего веб-сайта или неправильного предположения? Я никогда бы не подумал, что это может в основном сесть на сервер (II).
В ожидании, что люди расскажут мне, что я должен проверять наличие столбцов до того, как я их получу: я знаю об этом, и устаревший код теперь изменен, но это не мой вопрос, как описано выше, я бы хотел знать, почему последствия настолько резкие.
Обновление 2
Этот метод, вызываемый внутри DLL, запускает поток, который завернут в блок try-catch
:
[...]
try
{
ThreadStart starter = () => CreateReport(...)
Thread thread = new Thread( starter );
thread.Start();
if( !thread.Join( TimeSpan.FromMinutes( 15 ) ) )
{
// Log some timeout warning
}
else
{
// Log information about successful report generation
}
}
catch( Exception ex )
{
// Log error information
}
Ответы
Ответ 1
Скорее всего, ваш пул приложений автоматически отключается функцией IIS Rapid Fail Protection, как вы заметили в связанных вопросах. Если вы проверите свой журнал событий, может быть несколько необработанных исключений, которые будут выполняться быстро.
Проще говоря, достаточно необработанных исключений в настраиваемом промежутке времени (по умолчанию 5 в 5 минут) отключит AppPool, вызвав ответ 503 Service Unavailable.
Обоснование этой функции заключается в том, что если у вас есть неисправное приложение, вы, вероятно, не хотите, чтобы он автоматически перезапускался при каждом последующем запросе, потребляя ресурсы и, возможно, искажая данные.
Я должен признать, что это не было поведение по умолчанию, которое я ожидал бы.
Ознакомьтесь с объяснением Рика Сталса, это немного более подробно.
Чтобы действительно исправить это, вам нужно поймать исключение или предотвратить исключение исключения (например, @leppie предлагает). Необработанные исключения должны срывать весь процесс выполнения (что означает, что один процесс запроса/рабочего процесса, а не IIS) - он делает код .Net намного легче отлаживать, поскольку он не скрывает ошибки или просто висит приложение.
Обратите внимание, что это было изменено в .Net 2.0:
http://msdn.microsoft.com/en-us/library/ms228965.aspx
http://support.microsoft.com/kb/911816
Обновление
Основываясь на вашем обновлении выше, я не думаю, что ваше исключение действительно поймано, если оно выбрано из CreateReport()
. Этот метод выполняется в отдельном потоке:
![exception still thrown]()
Вам нужен try-catch в теле CreateReport()
, если его еще нет:
public static void CreateReport() {
try {
throw new Exception("reducto");
} catch {
Console.WriteLine("done did.");
}
}
Ответ 2
Это случилось со мной однажды. Реальная ошибка (в моем случае) была переполнением стека, которое закрывало пул.
Кажется, что IIS защищал себя от потребления слишком большого количества ресурсов.
Я нашел проблему с помощью DebugDiag.
Вот где я начал: http://www.webdebug.net/index.php/2012/12/collect-iis-crash-dump-with-debugdiag/
Я хотел бы понять, почему исключение во внешней DLL может привести к отключению пула приложений IIS, даже если исключение попадает в DLL, а также при вызове метода DLL из кода, стоящего за ASP. Страница .NET.
Внешняя dll также запускается в вашем пуле приложений. Большая авария в этой DLL также приведет к сбою вашего пула приложений. Некоторые исключения не могут обрабатываться, и исключение stackoverflow является одним из них. Тема обсуждается здесь. Возможно, это то, что происходит в вашем случае.