向大家分享一下最近排查“黑色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):
w3dt(可能是w3 data transfer的縮寫)是一個完成端口(Completion Port)處理程序,從http.sys的隊列(kernel-mode)中將請求取出至w3wp進程(user-mode)的本地隊列。
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又不開源,只能靠“蒙猜試”了。