ASP.Net請求處理機制初步探索之旅(1):前奏

發表於2015-03-18

開篇:ASP.Net是一項動態網頁開發技術,在歷史發展的長河中WebForm曾一時成為了ASP.Net的代名詞,而ASP.Net MVC的出現讓這項技術更加喚發朝氣。但是,不管是ASP.Net WebForm還是ASP.Net MVC在請求處理機制上大部分都是相同的,只是在請求處理管道上的處理事件做了不同的操作,因此,本文標題不區分ASP.Net WebForm和ASP.Net MVC,但在後續的介紹中會區分開來介紹。此外,本文以IIS經典模式為主,不討論整合模式(IIS7後加入了整合模式,不用載入外部的aspnet_isapi.dll元件)。

一、當一個請求到來時

①客戶端傳送一個請求給伺服器端

②一個HTTP請求對應一個HTTP報文

③HTTP.SYS元件捕獲請求,對報文作最基本的處理

HTTP.SYS是一個位於Windows Server和Windows XP SP2中的作業系統核心元件(核心模式中),能夠讓任何應用程式通過它提供的介面,以HTTP協議進行資訊通訊。

關於核心模式與使用者模式:

在Windows Server作業系統中,一個程式既可以執行於核心模式,也可以執行於使用者模式。如果一個程式執行於核心模式,那麼這個程式就可以訪問所有硬體和系統資料;如果一個進 程執行於使用者模式,那麼這個程式不能直接訪問硬體,而且訪問系統資料時也會受到限制。在Intel處理器架構中一共有0~3四個特權級,核心模式執行於0級之內,而使用者模式執行於3級。通過在核心模式執行Http.SYS,偵聽器可以直接訪問TCP/IP協議棧,但是又能夠位於www服務之外,這樣就不會受到應用程式中程式碼缺陷的影響,也不會因為應用程式崩潰而出現問題。

④如果該請求有快取內容則直接響應

HTTP.SYS元件的一個重要的作用就在於它有一個快取區,會將近期處理的響應結果放入這個快取區之中,如果再次請求這個內容,則會從快取區中取得內容並進行響應,提高了響應速度。而且, 靜態的內容現在被快取於核心模式下,這使服務響應速度更快

二、判斷是否動態資源

①IIS首先判斷請求的內容是否是靜態資源?

IIS首先會判斷請求的是否是靜態資源,如果是則直接到檔案系統中拿到請求的html/css/js/jpg/gif/png等資源直接響應請求。

②如果是動態資源則先查詢是由哪個擴充套件來處理?

IIS本身不會處理動態資源請求,它會根據請求的資源型別到一個被稱為“處理程式對映”中去查詢應該由哪個擴充套件程式來處理這個請求。在IIS中,對於asp.net的請求一般是由aspnet_isapi.dll這個元件來進行.net執行時的載入和具體請求的處理。有了基於ISAPI的擴充套件擴充套件程式,IIS伺服器就可以根據客戶端請求的資源副檔名,來決定應由哪個ISAPI擴充套件程式來處理客戶端請求,然後就可以將請求轉發給合適的ISAPI擴充套件程式。

關於IIS伺服器擴充套件:

由於IIS伺服器在設計時引入了開放的ISAPI介面標準,具備極高的可擴充套件性。在核心元件不變的情況下可靈活支援不同型別不同版本的ASP.NET應用程式。

關於ISAPI:

ISAPI(伺服器應用程式設計介面),它為開發人員提供了強大的可程式設計能力,只要按照標準介面開發不同型別的Web應用程式的ISAPI擴充套件程式,就能實現對IIS功能上的擴充套件,從而使IIS可以處理不同型別的客戶端請求。IIS管理器提供了應用程式配置功能,可以對不同的客戶端請求配置不同的ISAPI擴充套件程式。ISAPI擴充套件程式通常以DLL形式存在,可以被IIS載入並呼叫。

三、一個神奇的入口

①所謂Worker Process(工作者程式)

剛剛我們大體上介紹了IIS的處理步驟,但其實IIS對於動態資源的處理首先會通過一個工作程式去載入具體的處理元件dll。以IIS 6.0為例,如果IIS判斷它自己無法處理asp.net的請求,會由W3WP.exe所維護的工作程式來載入aspnet_isapi.dll。

②.NET執行時的載入

如果Web應用程式是第一次載入,那麼首先會由aspnet_isapi.dll載入.NET執行時(主要是呼叫伺服器上的.Net Framework建立CLR執行時)。而一個IIS工作程式裡有一個應用程式池,其中可以承載多個應用程式域AppDomain。

關於應用程式池:
應用程式池就是可以看成裝載計算機分配給動態網站的記憶體的容器。如果記憶體是水,那麼應用程式池就是魚缸,動態網站就是魚缸中的金魚。多個動態網站可以存在於同一個應用程式池裡,即魚缸中可以放多條金魚。當然,如果金魚多了,魚缸中的空間有限,金魚之間就會爭搶空間,不是很堅固的魚缸可能就會破裂,所有金魚都會受到影響。即是動態網站多了,記憶體不足,可能會造成記憶體級別的溢位漏洞,影響所有在那個應用程式池上的動態網站。

關於應用程式域:

使用.NET建立的可執行程式,並沒有直接承載到程式當中,而是承載到應用程式域(AppDomain)當中。應用程式域是.NET引入的一個新概念,它比程式所佔用的資源要少,可以被看作是一個輕量級的程式。

③應用程式域的載入

在.NET執行時建立好之後,通過應用程式域工廠AppDomainFactory建立應用程式域AppDomain。建立好AppDomain之後,就將請求轉給該AppDomain中的ISAPIRuntime物件,然後呼叫ISAPIRuntime物件的ProcessRequest()方法來進行處理。

ISAPIRuntme.ProcessRequest()方法是進入ASP.Net的第一個入口,ASP.Net的核心處理部分就剛剛開始。此篇我將其稱為前奏,是因為它是在ASP.Net的核心處理部分之前,將HTTP請求一步一步地傳遞給了ISAPIRuntime物件,後面我們再繼續探索ASP.Net的請求處理機制,今天就到此結束!

四、前奏流程總覽

參考資料

(1)Darren Ji,《ASP.NET MVC請求處理管道宣告週期的19個關鍵環節》:http://www.cnblogs.com/darrenji/p/3795661.html

(2)JackyXM,《HTTP.SYS詳解》:http://www.cnblogs.com/yxmx/articles/1652128.html

(3)木宛城主,《ASP.NET那點不為人知的事兒》:http://www.cnblogs.com/OceanEyes/archive/2012/08/13/aspnetEssential-1.html

(4)Tony He,《ASP.NET請求處理機制》:http://www.cnblogs.com/cilence/archive/2012/05/28/2520712.html

相關文章