最近几天,我们发现公司网站的主应用程序池服务的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证实了这一点,我也通过简单测试进行了确认。然而,至少有一个人最近在类似的环境中看到了类似的崩溃:Thread.Abort in ASP.NET app causes w3wp.exe to crash。(但这可能是一个无关的问题。) 我们的环境:
- 企业网站含购物车和合作伙伴网络服务,目标为.NET 4.5。(包括业务逻辑DLL和内部库在内的900,000多行自定义代码)
- 2个VMWare Web服务器使用Windows NLB组成负载均衡池
- 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。
我们部署了新版本的网页代码(每周进行多次)。自然地,我们对代码更改进行了双重检查,以防止可能存在的崩溃漏洞,但我们的更改似乎没有易受无限循环、递归堆栈溢出或高内存使用的风险——这些通常是w3wp.exe发生未处理异常时的罪魁祸首。有时崩溃会在几分钟内影响到一个Web服务器,但其他时候只有一个Web服务器受到影响。
我尝试过以下方法:
- 重新启动服务器并安装所有Windows更新。 - 分析IIS日志,查看是否在崩溃之前有任何可疑/恶意请求进入。我找不到任何模式——所有请求都看起来很正常。 - 启用w3wp.exe的自动崩溃minidump(如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:
我们现在已经重新应用了所有在故障排除中被删除的.NET 4.6之前的Windows更新,服务器已经运行了几天而没有崩溃。唯一剩下的需要重新应用的是.NET 4.6及其自身的更新,但我的管理层理所当然地不愿意安装可能会在生产中导致崩溃的东西。因此,我继续与微软合作分析不同的崩溃转储以确定问题所在。