與同步與非同步程式相關的 ASP.NET、IIS /CLR 執行緒和請求
我只是想在這裡澄清一些概念。如果有人願意分享他們在這件事上的專業知識,我們將不勝感激。
以下是我對IIS如何與執行緒相關的工作的理解,如果我錯了,請糾正我。
HTTP.sys
據我了解,對於 IIS 6.0(我現在將離開 IIS 7.0),Web 瀏覽器發出請求,被 HTTP.sys 核心驅動程序接收,HTTP.sys 將其交給 IIS 6.0 的執行緒池(I/ O執行緒?)和這樣的釋放自己。
IIS 6.0 執行緒/執行緒池
IIS 6.0 的執行緒返回將其交給 ASP.NET,ASP.NET 將臨時 HSE_STATUS_PENDING 返回給 IIS 6.0,這樣可以釋放 IIS 6.0 執行緒,然後將其轉發給 CLR 執行緒。
CLR 執行緒/執行緒池
當 ASP.NET 在 CLR 執行緒池中獲取一個空閒執行緒時,它會執行請求。如果沒有可用的 CLR 執行緒,它會在應用程序級隊列中排隊(性能很差)
所以基於之前的理解,我的問題如下。
- 在同步模式下,這是否意味著每 1 個 CLR 執行緒有 1 個請求?
*) 如果是這樣,在 1 個 CPU 上可以處理多少個 CONCURRENT 請求?還是我應該反過來問?每 1 個 CPU 如何允許 CLR 執行緒?比如說,允許 50 個 CLR 執行緒,這是否意味著它在任何給定時間都被限制為 50 個請求?使困惑。 2. 如果我將“processModle”配置中的“requestQueueLimit”設置為 5000,這究竟意味著什麼?您可以在應用程序隊列中排隊 5000 個請求嗎?那真的不是很糟糕嗎?既然應用程序隊列的性能很差,為什麼還要設置這麼高呢? 3. 如果您正在編寫非同步頁面,那麼它在上述過程中究竟從哪裡開始受益? 4. 我研究發現,預設情況下,IIS 6.0 的執行緒池大小為 256。5000 個並發請求進來,由 256 個 IIS 6.0 執行緒處理,然後由 256 個執行緒中的每一個處理,將其交給 CLR 執行緒,我猜這是偶數預設較低。這本身不是非同步的嗎?有點困惑。另外,同步模式下瓶頸在何時何地開始出現?並在非同步模式下?(不確定我是否有任何意義,我只是感到困惑)。 5. 當 IIS 執行緒池(全部 256 個)忙時會發生什麼? 6. 當所有 CLR 執行緒都忙時會發生什麼?(我假設所有請求都在應用程序級隊列中排隊) 7. 當應用程序隊列超過 requestQueueLimit 時會發生什麼?
非常感謝您的閱讀,非常感謝您在這件事上的專業知識。
您對向 CLR 的切換過程非常了解,但這裡是有趣的地方:
如果請求的每一步都是 CPU 綁定的/否則是同步的,是的:該請求將在其生命週期內佔用該執行緒。
但是,如果請求處理任務的任何部分超出了純託管程式碼(數據庫連接、文件讀/寫等)之外的任何非同步或什至任何與 I/O 相關的任務,則有可能(如果不可能)會發生這種情況:
- 請求進入 CLR 領域,由執行緒 A 拾取
- 請求呼叫文件系統
- 在幕後,到非託管程式碼的轉換發生在某個級別,這導致以類似回調的方式分配IO 完成埠執行緒(不同於普通執行緒池執行緒)。
- 一旦發生切換,執行緒 A返回到執行緒池,在那裡它能夠為請求提供服務。
- 一旦 I/O 任務完成,執行將重新排隊,假設執行緒 A 正忙 - 執行緒 B 接收請求。
這種“有趣”的行為也稱為“執行緒敏捷性”,這是盡可能避免在 ASP.NET 應用程序中使用任何執行緒靜態的原因之一。
現在,對於您的一些問題:
- 請求隊列限制是在請求開始被完全丟棄之前可以“排隊”的請求數。例如,如果您有一個異常“突發”的應用程序,您可能會收到很多非常短暫的請求,那麼將其設置為高可以防止請求被丟棄,因為它們會在隊列中聚集在一起,但同樣會很快耗盡。
- 非同步處理程序允許您創建與上述場景相同的“完成後給我打電話”類型的行為;例如,如果您說需要進行 Web 服務呼叫,則通過說一些 HttpWebRequest 呼叫同步呼叫該呼叫將預設阻塞直到完成,鎖定該執行緒直到它完成。非同步呼叫相同的服務(或非同步處理程序,任何 Begin/EndXXX 模式……)允許您控制誰實際被捆綁 - 您的呼叫執行緒可以繼續執行操作,直到該 Web 服務返回,這實際上可能是在請求已完成。
- 需要注意的一點是只有一個 ThreadPool - 所有非 IO 執行緒都從那里拉出,所以如果你將所有內容都移到非同步處理中,你可能會因為耗盡執行緒池做後台工作而不是服務請求而自責。