首页 > 代码库 > 云计算之路-阿里云上:“黑色1秒”最新线索——w3tp与w3dt

云计算之路-阿里云上:“黑色1秒”最新线索——w3tp与w3dt

向大家分享一下最近排查“黑色1秒”问题的进展,“黑色1秒”的问题表现详见什么是黑色1秒。

1. 发生在w3wp进程内

判断依据:“黑色1秒”期间,http.sys的HTTP Service Request Queues\ArriveRate正常,W3SVC_W3WP\Requests/Sec正常。

2. 请求未进入.NET线程池

判断依据:“黑色1秒”期间静态文件的请求也不能被处理,如果“黑色1秒”发生在.NET线程执行过程中,静态文件是由非托管模块处理的,应该不受影响。

3. 发生在处于user-mode的IIS核心模块

http.sys处于kernel-mode,处于user-mode的处理请求的IIS核心模块有:w3tp->w3dt->iiscore->webengine->wbhst_pm,在C:\Windows\System32\inetsrv中都有对应的dll文件。

IIS核心模块请求处理流程如下(自下而上,来自application pool crashes in IIS 7.5):

clr!ClrCreateManagedInstance  
webengine4!LegacyActivationShim::ClrCreateManagedInstance 
webengine4!GetIsapiProcessHost   
webengine!GetIsapiProcessHost     
wbhst_pm   
wbhst_pm!GetProtocolManager     
w3wphost!AppHostInitialize  
w3wphost!IPM_MESSAGE_PIPE::operator= 
iiscore!W3_SERVER::GetProtocolManagerCustomInterface   
webengine4!InitClrHost    
webengine4!CMgdEngGlobalModule::OnGlobalApplicationResolveModules   
iiscore!VIRTUAL_MODULE::GlobalDoWork  
iiscore!W3_SERVER::GlobalNotify  
iiscore!W3_APPLICATION::ResolveModules    
iiscore!W3_APPLICATION::SetupNotificationContext   
iiscore!W3_CONTEXT::SetupStateMachinePhase2   
iiscore!W3_CONTEXT::SetupStateMachine   
iiscore!W3_MAIN_CONTEXT::StartNotificationLoop   
iiscore!W3_MAIN_CONTEXT::OnNewRequest  
w3dt!UL_NATIVE_REQUEST::DoStateProcess   
w3dt!UL_NATIVE_REQUEST::DoWork   
w3dt!OverlappedCompletionRoutine 
w3tp!THREAD_POOL_DATA::ThreadPoolThread      
w3tp!THREAD_MANAGER::ThreadManagerThread

4. w3tp与w3dt

w3tp(w3 thread pool)是IIS的线程池,在注册表(HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\InetInfo\Parameters)中有一个设置项ThreadPoolStartDelay,默认值是1秒。

ThreadPoolStartDelay is how long the thread pool should set the timer for when zero threads are waiting on the completion port.

如果有线程在等待完成端口,是这样的情况(以下截图来自Process Explorer):

W3TP.dll!ThreadPoolBindIoCompletionCallback

w3dt(可能是w3 data transfer的缩写)是一个完成端口(Completion Port)处理程序,从http.sys的队列(kernel-mode)中将请求取出至w3wp进程(user-mode)的本地队列。

I/O Completion Port

5. 猜想

在w3dt将请求从http.sys的队列搬至w3wp本地队列后,本应触发iiscore!W3_MAIN_CONTEXT::OnNewRequest;可是这时某种未知原因(怀疑是CPU的原因)造成w3tp认为"zero threads are waiting on the completion port",将Timer频率改为了1秒,结果1秒后才触发OnNewRequest,将队列中请求转交至后续处理环节;而在这1秒期间,ASP.NET由于没有收到请求,于是QPS为0。

感慨:网上关于IIS核心模块的资料实在太少了,IIS又不开源,只能靠“蒙猜试”了。