为什么从 ASP.NET 页面调用的 DLL 中出现异常后,我的 IIS7 应用程序池会关闭?

2024-05-09

我已阅读帖子ASP.NET应用程序池关闭问题 https://stackoverflow.com/questions/4742122/asp-net-application-pool-shutdown-problem and IIS 7.5:应用程序池问题 https://stackoverflow.com/questions/5486482/iis-7-5-problem-with-application-pool但他们没有回答我的问题。

我有一个 C# ASP.NET 页面,它在代码隐藏中实例化通过 BIN 目录提供的 DLL 中的类,然后调用该实例上的方法。 DLL 内的方法抛出异常System.ArgumentException由于 a 中不存在列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)。我必须手动重新启动应用程序池,站点才能再次工作。

Update按照要求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)服务器瘫痪。

预计人们会告诉我,我应该在访问列之前检查列是否存在:我知道这一点,并且遗留代码现已更改,但这不是我上面描述的问题,我想知道为什么后果是如此严重。

Update 2

在 DLL 内部调用的相关方法会启动一个包装在try-catch block:

[...]
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
}

您的应用程序池很可能被自动关闭IIS 的快速故障保护 http://www.iis.net/configreference/system.applicationhost/applicationpools/add/failure正如您在链接的问题中注意到的那样。如果您检查事件日志,可能会快速连续抛出多个未处理的异常。

简而言之,在可配置的时间跨度(默认为 5 分钟内 5 个)内出现足够多的未处理异常将关闭 AppPool,导致 503 Service Unavailable 响应。

此功能背后的原因是,如果您有一个错误的应用程序,您可能不希望它在每个后续请求时自动重新启动,从而消耗资源并可能损坏数据。

我必须承认这也不是我所期望的“默认”行为。

查看里克·斯塔尔斯的解释 http://www.west-wind.com/weblog/posts/2006/Dec/19/IIS-7-and-Rapid-Fail-Protection,有点深入了。

要真正解决此问题,您需要捕获异常,或防止引发异常(就像 @leppie 建议的那样)。未处理的异常应该会破坏整个执行进程(意味着单个请求/工作进程,而不是 IIS) - 它使 .Net 代码更容易调试,因为它不会隐藏错误或简单地挂起应用程序。

请注意,这在 .Net 2.0 中发生了变化:
http://msdn.microsoft.com/en-us/library/ms228965.aspx http://msdn.microsoft.com/en-us/library/ms228965.aspx
http://support.microsoft.com/kb/911816 http://support.microsoft.com/kb/911816

Update
根据您上面的更新,我认为您的异常实际上不会被捕获,如果它是从CreateReport()。该方法在单独的线程上执行:

你需要在主体中进行尝试捕获CreateReport()如果还没有:

public static void CreateReport() {
    try {
        throw new Exception("reducto");
    } catch {
        Console.WriteLine("done did.");
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么从 ASP.NET 页面调用的 DLL 中出现异常后,我的 IIS7 应用程序池会关闭? 的相关文章

随机推荐