Agenda
- 前言:
- IIS 與 Asp net (W3SVC服務)
- IISAPIRuntime介面
- IsapiRunTime.ProcessRequest
- HttpRuntime.ProcessRequestNoDemand
- 小結
前言:
上一篇我們介紹HttpModule & HttpHandler
對於
今天正式進入.Net CLR
處理Http請求的世界.
先附上Asp.net
執行請求流程圖.
現在開始講解藍色區塊.
查看原始碼好站 Reference Source
IIS 與 Asp net (W3SVC服務)
World Wide Web Publishing Service
(簡稱W3SVC
)是一個Window Service.
W3SVC
在SvcHost.exe
這個應用程式上被執行.
W3SVC
主要功能
- HTTP請求的監聽
- 工作執行緒的管理以及配置管理
當檢測到某個HTTP Request
後,先根據一個註冊表判斷請求的副檔名是否是靜態資源(比如.html,.img,.txt,.xml
…)
如果是則直接將文件內容以HTTP Response的形式返回。
如果是動態資源(比如.aspx,asp,php
等等),則通過副檔名從IIS
的Script Map
找到相應ISAPI.dll
IISAPIRuntime介面
前面說到透過W3SVC
服務
System.Web.Hosting.IISAPIRuntime
這個介面是一個基於COM
的Interface
,ASP.NET ISAPI
可以通過COM
的方式調用實現該Interface
的Class
物件的ProcessRequest
方法,從非託管環境進入了託管的環境。
1 | [ ] |
所以
IISAPIRuntime.ProcessRequest
是我們探討原始碼起始點.
IsapiRunTime.ProcessRequest
一開始會先呼叫IsapiRunTime
的ProcessRequest
方法來執行此次請求.
在CreateWorkerRequest
會依據不同IIS版本建立不同ISAPIWorkerRequest
物件,之後在呼叫Initialize
方法把Http
請求內容初次填入這個對象.
1 | public int ProcessRequest(IntPtr ecb, int iWRType) { |
這段程式碼有幾個重點:
- 把Http請求內文封裝到
WorkerRequest
物件中,方便日後使用. wr.Initialize()
初始化WorkerRequest
物件- 呼叫
HttpRuntime.ProcessRequestNoDemand
方法並把剛剛初始化的WorkerRequest
物件當作參數傳入.
其中參數ecb
(Execution Control Block
)是一個Unmanaged Pointer
ISAPIRuntime
不能直接調用ASP.NET ISAPI
,所以通過一個ecb
物件指標,ecb
實現ISAPI
和ISAPIRutime
之間溝通.
HttpRuntime.ProcessRequestNoDemand
先來看看剛剛呼叫的HttpRuntime.ProcessRequestNoDemand
方法.
這裡需要注意兩個重點.
判斷目前執行程序池是否已經超過負荷,如果是會把
wr
物件指向null
1
2if (rq != null)
wr = rq.GetRequestToExecute(wr);如果
wr!=null
(代表還有資源可以執行請求)就呼叫ProcessRequestNow
方法會繼續呼叫ProcessRequestInternal
方法.
1 | internal static void ProcessRequestNoDemand(HttpWorkerRequest wr) { |
ProcessRequestInternal
在HttpRuntime
很重要的方法之一是ProcessRequestInternal
下面程式碼,我把
ProcessRequestInternal
方法中註解移除且只貼出我覺得重要的程式碼
此方法有做幾個事情:
- 如果Server很忙碌回傳
wr.SendStatus(503, "Server Too Busy");
- 利用
HttpWorkerRequest
物件封裝我們常常使用HttpContext
- 透過
HttpApplicationFactory.GetApplicationInstance
返回一個IHttpHandler
物件 - 如果返回的
IHttpHandler
物件支援異步請求優先執行,不然就執行同步請求.
上面第3,4點最為重要,因為我們就可以很清楚了解到為什麼最後都會找到一個繼承IHttpHandler
介面的物件來執行ProcessRequest
方法.
因為Asp.net
在HttpRunTime
程式碼中倚賴一個IHttpHandler
介面抽象才造就具有彈性的系統架構.
1 | private void ProcessRequestInternal(HttpWorkerRequest wr) { |
下面此這個方法執行時兩個小重點.
ProcessRequestInternal
方法初始化我們常用HttpContext
物件,把Http
內容封裝到這個類別中.
如果返回
IHttpHandler
物件支援異步請求優先執行,不然就執行同步請求.
小結
今天我們學到
ISAPIRunTime.ProcessRequest
方法- 建立一個
WorkerRequest
物件把Http內容封裝到裡面,並呼叫 HttpRuntime.ProcessRequestNoDemand
方法.
- 建立一個
HttpRuntime.ProcessRequestNoDemand
方法- 檢查目前是否有資源可以處理請求
- 封裝
HttpContext
並初始化內容資料 - 利用
HttpApplicationFactory.GetApplicationInstance
取得IHttpHanlder
物件 - 呼叫
IHttpHanlder
ProcessRequest
方法
下篇我們會來好好介紹HttpApplicationFactory
這個工廠到底如何返回IHttpHanlder
物件.
此文作者:Daniel Shih(石頭)
此文地址: https://isdaniel.github.io/ithelp-day3/
版權聲明:本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 3.0 TW 許可協議。轉載請註明出處!