【发布时间】:2016-01-05 05:17:13
【问题描述】:
在过去的几天里,我们看到为我们公司网站的主应用程序池提供服务的 w3wp.exe 工作进程间歇性崩溃。有时崩溃是孤立的,IIS 能够成功地重新启动工作进程。但如果 5 分钟内发生超过 5 次崩溃,IIS 快速故障保护就会启动并停止应用程序池。以下是崩溃前应用程序事件日志中的示例条目:
An unhandled exception occurred and the process was terminated.
Application ID: /LM/W3SVC/2/ROOT
Process ID: 3640
Exception: System.Threading.ThreadAbortException
Message: Thread was being aborted.
StackTrace: at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)
at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
在由于 ThreadAbortException 导致的崩溃之后,立即记录了一个更严重的事件:
Faulting application name: w3wp.exe, version: 8.0.9200.16384, time stamp: 0x5010885f
Faulting module name: KERNELBASE.dll, version: 6.2.9200.17366, time stamp: 0x554d16f6
Exception code: 0xe0434352
Fault offset: 0x00010192
Faulting process id: 0xe38
Faulting application start time: 0x01d100dc662652d6
Faulting application path: C:\Windows\SysWOW64\inetsrv\w3wp.exe
Faulting module path: C:\Windows\SYSTEM32\KERNELBASE.dll
Report Id: db5b0d5b-6cd0-11e5-9418-005056900458
Faulting package full name:
Faulting package-relative application ID:
现在,ThreadAbortException 永远不会导致 w3wp.exe 崩溃,因为每次执行标准 Response.Redirect() 时都会抛出它。 MSDN confirms this,我还用simple test 确认了这一点。但是,最近至少有一个人在类似的环境中看到了类似的崩溃:Thread.Abort in ASP.NET app causes w3wp.exe to crash。 (但这可能是一个不相关的问题。)
我们的环境:
- 带有购物车和合作伙伴网络服务的企业网站;针对 .NET 4.5。 (超过 900,000 行自定义代码,包括业务逻辑 DLL 和内部库。)
- 使用 Windows NLB 的负载平衡池中的 2 个 VMWare Web 服务器
- IIS 8.0 / Windows 2012 Server Standard / .NET 4.6.00081
- 应用程序池在 32 位模式下运行,因为我们必须支持少数调用旧版 VB6 DLL 的经典 ASP 页面。
背景:
在崩溃开始前几天,我们升级到了 .NET 4.6。我们启用了新的 RyuJIT(默认设置),并安装了所有更新以解决此处描述的关键编译器问题:http://blogs.msdn.com/b/dotnet/archive/2015/07/28/ryujit-bug-advisory-in-the-net-framework-4-6.aspx。
我们还部署了新版本的 Web 代码(我们每周都会这样做几次)。自然,我们仔细检查了代码更改是否存在任何潜在的崩溃漏洞,但我们的任何更改似乎都不会受到无限循环、递归堆栈溢出或高内存使用率的影响——当 w3wp.exe 因未处理的异常而崩溃时,这些都是正常的罪魁祸首。
有时崩溃会在几分钟内影响到另一台网络服务器,但有时只有一台网络服务器受到影响。
我尝试过的事情:
- 重新启动服务器并安装所有 Windows 更新。
- 分析 IIS 日志以查看在崩溃前是否有任何可疑/错误请求进入。我找不到任何模式——所有请求 看起来很正常。
- 为 w3wp.exe 启用自动崩溃小型转储(如 https://msdn.microsoft.com/en-us/library/bb787181.aspx 所述)并使用 WinDbg 对其进行分析。不幸的是,CLR“感兴趣的堆栈跟踪”没有显示任何有用的信息,只是几个与我们的代码无关的空 GC 帧:
> 0:026> !clrstack > OS Thread Id: 0x1ff0 (26) > Child SP IP Call Site > 2321f96c 771bdf8c [GCFrame: 2321f96c] > 2321f9a4 771bdf8c [GCFrame: 2321f9a4]
有什么想法吗?
更新:
我们已在我们的 Web 服务器上回滚 .NET 4.6 和最近的 Windows 更新。我们已经对此进行了 2 或 3 天的监控,具体取决于服务器回滚的时间,并且在每种情况下,尽管维护相同的应用程序代码,但随后的崩溃都为零。 这非常明确地证明 .NET 4.6 或其他 Windows 更新导致了间歇性崩溃,不是我们的代码,因为 w3wp.exe 之前每天会崩溃几次。
我们现在正试图向 Microsoft 支持证明这一点,但这是一场艰苦的战斗,因为问题是随机的、间歇性的,而且我们无法可靠地重现它。 (他们提供了dump analysis,但它似乎是一个红鲱鱼。)我们也在分组重新应用更新并等待几天观察崩溃,以努力隔离错误的更新。显然这是一个乏味的过程。
更新 #2:
我们现在重新应用了在故障排除中删除的所有 pre-.NET 4.6 Windows 更新,并且服务器已经运行了几天而没有崩溃。唯一需要重新应用的是 .NET 4.6 和它自己的更新,但我的管理层不愿意安装可能会导致生产崩溃的东西,这是可以理解的。因此,我将继续与 MS 合作分析不同的故障转储以查明问题。
【问题讨论】:
-
您是否在站点代码中手动启动任何线程?
-
@mason 是的,我们的代码多年来一直在这样做以并行化某些中等长度的 API 调用。但从来都不是问题,最近那部分代码也没变过。
-
任何与 HTTP 请求无关的线程中的异常都会导致进程中断。我敢打赌它与 .NET 4.6 无关,这可能是巧合。你不应该启动自己的线程。根据任务的持续时间,您可能能够使用基于任务的异步编程,或者转向在后台运行该代码的其他方法。请参阅 Phil Haack 和 Scott Hanselman 的博文。
-
@mason 总的来说,我同意我们不应该启动自己的线程。但是我们有一个用例,我们希望同时调用多个不同的 API 并严格控制使用的线程数(每个合作伙伴一个,通常一次只有几十个)和持续时间(大约 30 秒)。因此,对于这一点,我们喜欢手动线程为我们提供的精细控制,而不是像任务这样的线程池支持的实现。无论如何,如果我们的一个用户线程被手动中止,崩溃转储堆栈跟踪不会显示吗?我想会尝试重现这种情况。
-
你试过禁用整机的RyuJIT吗?我们遇到了有趣的问题。
标签: asp.net iis crash w3wp .net-4.6