为啥我的 IIS7 应用程序池在从 ASP.NET 页面调用的 DLL 中出现异常后关闭?
Posted
技术标签:
【中文标题】为啥我的 IIS7 应用程序池在从 ASP.NET 页面调用的 DLL 中出现异常后关闭?【英文标题】:Why does my IIS7 application pool shutdown after an exception in a DLL called from an ASP.NET page?为什么我的 IIS7 应用程序池在从 ASP.NET 页面调用的 DLL 中出现异常后关闭? 【发布时间】:2013-04-05 05:02:58 【问题描述】:我已经阅读了ASP.NET application pool shutdown problem 和IIS 7.5: problem with Application pool 的帖子,但他们没有回答我的问题。
我有一个 C# ASP.NET 页面,它在代码隐藏中从通过 BIN 目录提供的 DLL 实例化一个类,然后在此实例上调用一个方法。由于DataRow
对象中不存在列,DLL 中的方法会抛出System.ArgumentException
。事件日志显示以下错误:
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)。我必须手动重新启动应用程序池,然后站点才能再次运行。
更新
根据后面 ASP.NET 代码的要求,try catch
块:
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 );
现在我的问题是,为什么在尝试访问不存在的DataRow
列时抛出一个相对“简单”的异常(例如System.ArgumentException
)会导致整个网站崩溃? ASP.NET 页面的通用 try-catch
块也没有帮助,这也不应该是使整个网站完全不可用的原因,或者这是一个错误的假设?我从没想过这基本上可以让(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
【问题讨论】:
catch 块中发生了什么?如果这引发异常,您可能会遇到麻烦。可以贴一下try catch代码吗? catch 块调用的方法只是使错误消息对客户端(浏览器)可见,我将更新我的问题。 开个玩笑——如果你完全删除 try-catch 块并调用该方法,应用程序池是否仍然崩溃? 回到工作岗位时试试:-) 和以前一样。删除 ASP.NET 页面背后代码的异常处理会导致应用程序池关闭。 【参考方案1】:正如您在链接问题中所指出的,您的应用程序池很可能会被 IIS's Rapid Fail Protection 功能自动关闭。如果您检查事件日志,可能会快速连续抛出多个未处理的异常。
简单地说,在可配置的时间跨度内(默认为 5 分钟内 5 次)有足够多的未处理异常将关闭 AppPool,从而导致 503 Service Unavailable 响应。
此功能背后的原因是,如果您的应用程序有问题,您可能不希望它在每次后续请求时自动重新启动,从而消耗资源并可能损坏数据。
我不得不承认这也不是我所期望的“默认”行为。
查看Rick Stahls explanation,它更深入一点。
要真正解决这个问题,您需要捕获异常,或防止抛出异常(就像@leppie 建议的那样)。未处理的异常应该会破坏整个执行进程(意味着单个请求/工作进程,而不是 IIS)——它使 .Net 代码更容易调试,因为它不会隐藏错误或简单地挂起应用程序。
请注意,这在 .Net 2.0 中已更改:http://msdn.microsoft.com/en-us/library/ms228965.aspxhttp://support.microsoft.com/kb/911816
更新
根据您上面的更新,我认为您的异常实际上不会被捕获,如果它是从CreateReport()
抛出的。该方法在单独的线程上执行:
如果CreateReport()
的正文中还没有,你需要一个 try-catch:
public static void CreateReport()
try
throw new Exception("reducto");
catch
Console.WriteLine("done did.");
【讨论】:
感谢您提供更详细的信息,尽管我仍然不明白为什么在 DLL 中捕获的异常会导致应用程序池关闭。快速连续抛出的多个异常也不应该是这种情况,因为 DLL 方法的执行会随着第一个异常被抛出而终止。事件日志还显示只生成了一个异常。 谢谢,我会尽快找到时间进行验证 - 我们刚刚将 TFS 移到了不同的网络,并且仍在重新加快速度,非常抱歉对于延迟,请耐心等待几天。 就是这样,确实有点隐蔽。该方法中有一个try catch
块,但它只捕获了一种(不同的)异常,当我遇到问题中描述的问题时,这种异常没有发生。再次感谢:-)【参考方案2】:
它曾经发生在我身上。真正的错误(在我的情况下)是关闭池的堆栈溢出。
似乎 IIS 正在保护自己免于消耗过多资源。
我使用 DebugDiag 发现了问题。
我从这里开始:http://www.webdebug.net/index.php/2012/12/collect-iis-crash-dump-with-debugdiag/
我想了解为什么外部 DLL 中的异常会导致 IIS 应用程序池关闭,即使异常在 DLL 中被捕获,并且在从 ASP 后面的代码中调用 DLL 的方法时也是如此.NET 页面。
外部 dll 也在您的应用程序池中运行。此 dll 中的重大崩溃也会使您的应用程序池崩溃。有些异常无法处理,*** 异常就是其中之一。讨论主题here。也许这就是你的情况。
【讨论】:
以上是关于为啥我的 IIS7 应用程序池在从 ASP.NET 页面调用的 DLL 中出现异常后关闭?的主要内容,如果未能解决你的问题,请参考以下文章
我需要更改啥以允许我的 IIS7 ASP.Net 3.5 应用程序创建事件源并将事件记录到 Windows EventLog?