ISAPI_Rewrite引起的IIS应用程序池崩溃(fatal communication error)
在园子的发展过程中,曾经遭遇过多次应用程序池崩溃问题(比如: 为什么应用程序池总是崩溃 ),每次都被搞得精疲力尽,后来稀里糊涂地解决了问题,却没找到问题的真正原因。
而这一次,一天内解决了问题并找到了真正原因。这次与以前有什么不同呢?我想主要的不同是面对问题时心态的改变。心态一变,一切随之而变。
在去年阻挡淘宝图片外链造成的巨量请求时( 满园尽是503,记曾经的一次IIS 7性能考验 ),ISAPI_Rewrite曾经立下了汗马功劳,而这次它却是罪魁祸首。一切皆有可能,解决问题时,不要主观地忽视一些因素。
遇到Crash问题,用WinDbg分析dump文件是王道。之前由于觉得它高深、复杂,不敢轻易用它。而这次只用了两个命令,就找到了问题的线索。做一件事情,要从最难、你最害怕的地方着手。
在解决问题的过程中,这篇文章( Debugging Faulting Application w3wp.exe Crashes )给了我很大的帮助,感谢作者 Paul White !
下面分享一下问题的解决过程:
一、系统环境
IIS 7.5 + ASP.NET 4 X64 + Managed Pipeline Mode(Integrated) + ISAPI_Rewrite
注: ISAPI_Rewrite 是一个进行URL重写的ISAPI Filter。
猜测1:问题可能与应用程序池以集成模式运行有关,IIS用托管程序处理请求,而ISAPI_Rewrite是非托管程序。
猜测2:请求是由System.Web.Hosting.PipelineRuntime转发给ISAPI_Rewrite的。
二、问题的现象
1. 在事件日志中的体现:
Event ID 5011:
A process serving application pool 'cnblogs_com' suffered a fatal communication error with the Windows Process Activation Service. The process id was '10740'. The data field contains the error number.
Event ID 1000:
Faulting application name: w3wp.exe, version: 7.5.7600.16385, time stamp: 0x4a5bd0eb
Faulting application start time: 0x01cc55c536f78bbc
Faulting application path: c:\windows\system32\inetsrv\w3wp.exe
Faulting module path: C:\Windows\SYSTEM32\ntdll.dll
Event ID 1001:
Event Name: APPCRASH
Response: Not available
Problem signature:
P1: w3wp.exe
P3: 4a5bd0eb
P4: ntdll.dll
P9:
P10:
Attached files:
These files may be available here:
Analysis symbol:
2. 用户访问时的体现:
如果用户在发出请求后服务器响应的过程中发生Crash(这是猜测,不一定准确),浏览器一直处于连接加载状态,直到出现连接超时或连接重置错误。
如果在Crash已发生时,用户发出访问请求,浏览器会显示:The service is unavailable.
Crash发生后,当前W3P进程会重启,这时访问速度会慢。
另外:由于W3P进程会经常重启,也会造成CPU占用偏高。
三、问题分析
从上面的事件日志1001可以看出,发生Crash时,系统会生成dump文件,文件存放的位置就在日志内容中。
运行WinDbg,通过File>Open Crash Dump打开dump文件(比如WER3300.tmp.hdmp),如下图:
在命令框中输入.loadby sos clr,结果如下图:
继续在命令框中输入!clrstack,结果如下:
0:074> !clrstack
...
OS Thread Id: 0x18d0 (74)
Child SP IP Call Site
0000000010ccf048 0000000076ddfc6a [NDirectMethodFrameStandalone: 0000000010ccf048] System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion (IntPtr, System.Web.RequestNotificationStatus ByRef)
0000000010ccf010 000007fef17bf997 DomainNeutralILStubClass.IL_STUB_PInvoke(IntPtr, System.Web.RequestNotificationStatus ByRef)*** WARNING: Unable to verify checksum for System.Web.ni.dll
*** ERROR: Module load completed but symbols could not be loaded for System.Web.ni.dll
0000000010ccf0e0 000007fef1898994 System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr, IntPtr, IntPtr, Int32)
0000000010ccf280 000007fef1898d32 System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr, IntPtr, IntPtr, Int32)
0000000010ccf2d0 000007fef1896e51 DomainNeutralILStubClass.IL_STUB_ReversePInvoke(Int64, Int64, Int64, Int32)
0000000010ccf538 000007fef974a7bb [ContextTransitionFrame: 0000000010ccf538]
从上面的结果看,Crash是在调用System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion方法时发生的。
用 ILSpy 查看一下 MgdIndicateCompletion 的代码:
webengine.dll是什么东东?当时我们没有深究。从这里的代码可以看出这是一个非托管调用,也就是Crash发生在非托管调用时。于是,我们就分析哪些地方会引发非托管调用,能想到的唯一地方就是ISAPI_Rewrite.
同时,我们在网上发现了一篇 ISAPI_Rewrite引起应用程序池Crash的文章 ,而且异常信息显示Crash也是发生在调用System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion时。
难道真的是ISAPI_Rewrite引起的?当时从感情上有点不愿接受,它曾经立过汗马功劳!。。。可能由于之前对它的好感,一直把它忽视了,现在它作为怀疑对象突然出现在眼前,虽然感情有些不能接受,但直觉上觉得就是它。
四、问题解决
别无选择!立即撤下ISAPI_Rewrite,换上 URL Rewrite module 。(当然其中的过程没这么轻松,要改URL重写规则)
自从昨天晚上换过后,事件日志中的错误信息再也没有出现,CPU占用也降下来了,访问页面也没遇到速度慢、连接超时/重置的问题。
我们终于可以欢呼:这一次,我们成功地解决了IIS应用程序池崩溃的问题!
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于ISAPI_Rewrite引起的IIS应用程序池崩溃(fatal communication err的详细内容...