IIS 6.0上的ASP.NET处理突然停止

时间:2009-11-30 08:42:16

标签: asp.net iis-6 nullreferenceexception

我们在其中一个网络应用程序中发现了一个相当奇怪的行为。在本地开发人员工作站上进行调试时,一切都处理得很好(使用Cassini Developement Webserver)。使用IIS 6.0在远程Web服务器上发布时,处理运行大约4或5分钟,然后突然死亡。

我稍后会解释“突然死亡”的含义,首先我想提供一段失败的代码摘录。

// loads data from SAP Webservice and serializes it into database    
LoadXMLDataFromSAP();

// loop each item of a certain structure and parse data
foreach (var xItem in xSapData)
{
    // method determining a status, about 30 LOC, fast execution
    GetStatusCodeForContract(xItem);

    ...

    // methods to parse data blocks, about 400 LOC, slow execution (database etc.)
    TimeconsumingParserMethod1(xItem);
    TimeconsumingParserMethod2(xItem);
}

这个代码在调试时运行正常,执行大约需要13分钟(没关系,因为只有在与SAP同步所有数据时才会发生)。在IIS 6.0上针对SAME SAP数据源运行SAME代码时,执行将在4或5分钟后停止。

首先,程序在调用“TimeconsumingParserMethod1()”时抛出System.NullReferenceException,在下一个循环中,我们在“GetStatusCodeForContract()”上得到System.NullReferenceException。由于我们在两个调用中使用相同的参数,我认为抛出了NullReferenceException,因为成员“xItem”为null。

服务器配置:

8 Core Intel machine
4 GB of RAM
RequestTimeout = 900 (15 minutes)
Memory usage = unlimited

有人知道IIS 6或类似的生产服务器环境中的这种行为吗?

1 个答案:

答案 0 :(得分:0)

好吧,我终于找到了问题所在。由于我们本地测试服务器上的EventLog存在一些问题,我没有注意到一些IIS异常。

问题的根源不是任何超时设置,它是ASP.NET 2.0的AppDomain回收行为。如果在webrequest期间更改了很多文件夹结构,则会重新加载AppDomain,从而导致神秘的NullReferenceExceptions。

以下文章帮助我追踪了这个问题:http://weblogs.asp.net/owscott/archive/2006/02/21/ASP.NET-v2.0-2D00-AppDomain-recycles_2C00_-more-common-than-before.aspx

链接下方的代码段是使用的解决方法(它只是禁用子文件夹的文件监控,对web.config和程序集的更改仍然会重新加载AppDomain以进行自动部署)。

System.Reflection.PropertyInfo p = typeof(System.Web.HttpRuntime).GetProperty("FileChangesMonitor", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);

object o = p.GetValue(null, null);

System.Reflection.FieldInfo f = o.GetType().GetField("_dirMonSubdirs", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.IgnoreCase);

object monitor = f.GetValue(o);

System.Reflection.MethodInfo m = monitor.GetType().GetMethod("StopMonitoring", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); m.Invoke(monitor, new object[] { });
相关问题