IIS/ASP.NET 管道
ASP.NET MVC 是建立在 ASP.NET 平臺(tái)上基于 MVC 模式的 Web 應(yīng)用框架,深刻理解 ASP.NET MVC 的前提是對(duì) ASP.NET 管道式設(shè)計(jì)具有深刻的認(rèn)識(shí)。由于 ASP.NET Web 應(yīng)用大都寄宿于 IIS 上,將兩者結(jié)合起來(lái)了解在 IIS 和 ASP.NET 管道中是如何流動(dòng)的。
IIS5.x與ASP.NET
IIS5.x 是如何處理基于 ASP.NET 資源(如.aspx、.asmx...)請(qǐng)求的呢?
IIS5.x運(yùn)行在進(jìn)程 InetInfo.exe 中,該進(jìn)程寄存著一個(gè)名為 World Wide Web Publishing Service(簡(jiǎn)稱(chēng)W3SVC)的 Windows 服務(wù)。W3SVC 主要負(fù)責(zé) HTTP 請(qǐng)求的監(jiān)聽(tīng)、激活、管理工作進(jìn)程、加載配置(從 Metabase 中加載相關(guān)配置信息)等。
IIS5.x與ASP.NET
當(dāng)檢測(cè)到某個(gè) HTTP 請(qǐng)求時(shí),IIS 先根據(jù)擴(kuò)展名判斷請(qǐng)求的是靜態(tài)資源還是動(dòng)態(tài)資源。對(duì)于靜態(tài)資源 IIS 會(huì)將文件內(nèi)容直接響應(yīng)給客戶(hù)端,對(duì)于動(dòng)態(tài)資源則通過(guò)擴(kuò)展名從 IIS 的腳本映射(Script Map)中找到相應(yīng)的ISAPI 動(dòng)態(tài)鏈接庫(kù)(Dynamic Link Library, DLL)。
ISAPI(Internet Server Application Programming Interface)是一套本地的(Native)Win32 API,是 IIS 和其他動(dòng)態(tài) Web 應(yīng)用或平臺(tái)之間的紐帶。
ISAPI 定義在一個(gè)動(dòng)態(tài)鏈接庫(kù)(DLL)文件中, ASP.NET ISAPI 對(duì)應(yīng)的 DLL 文件名稱(chēng)為 aspnet_isapi.dll,位于 %windir%\Microsoft.NET\Framework\{version no}\中。
ISAPI 支持 ISAPI 擴(kuò)展(ISAPI Extension)和 ISAPI 篩選(ISAPI Filter),前者是真正處理 HTTP 請(qǐng)求的接口,后者則可以在 HTTP 請(qǐng)求真正被處理之前查看、修改、轉(zhuǎn)發(fā)、拒絕請(qǐng)求,比如 IIS 可利用 ISAPI 篩選進(jìn)行請(qǐng)求的驗(yàn)證。
若請(qǐng)求的是一個(gè)基于 ASP.NET 的資源類(lèi)型,如.aspx、.asmx、.svc等,aspnet_isapi.dll 會(huì)被加載,ASP.NET ISAPI 隨后會(huì)創(chuàng)建 ASP.NET 的工作進(jìn)程(若該進(jìn)程尚未啟動(dòng))。對(duì)于 IIS5.x 來(lái)說(shuō),該工作進(jìn)程為 aspnet.exe。IIS 進(jìn)程與工作進(jìn)程之間通過(guò)命名管道(Named Pipes)進(jìn)行通信。
在工作進(jìn)程初始化過(guò)程中,.NET 運(yùn)行時(shí)(CLR)會(huì)被加載以構(gòu)建一個(gè)托管的環(huán)境。對(duì)于某個(gè) Web 應(yīng)用的初次請(qǐng)求,CLR 會(huì)被其創(chuàng)建一個(gè)應(yīng)用程序域(Application Domain)。
在應(yīng)用程序域中,HTTP 運(yùn)行時(shí)(HTTP Runtime)被加載并用以創(chuàng)建相應(yīng)的應(yīng)用。寄存于 IIS5.x 的所有Web應(yīng)用都運(yùn)行在同一個(gè)進(jìn)程(工作進(jìn)程 aspnet_wp.exe)的不同應(yīng)用程序域中。
IIS6.0 與 ASP.NET
IIS5.x存在兩個(gè)方面的不足:
- ISAPI動(dòng)態(tài)鏈接庫(kù)被加載到 InetInfo.exe 進(jìn)程中,它和工作進(jìn)程之間是一種典型的跨進(jìn)程通信方式,盡管采用命名管道,仍會(huì)帶來(lái)性能瓶頸。
解決方案:IIS6.0將ISAPI動(dòng)態(tài)鏈接庫(kù)直接加載到工作進(jìn)程中
- ASP.NET 應(yīng)用運(yùn)行在相同進(jìn)程 aspnet_wp.exe 的不同程序域中,基于應(yīng)用程序域的隔離不能從根本上解決一個(gè)應(yīng)用程序?qū)α硪粋€(gè)程序的影響,需不同的Web應(yīng)用運(yùn)行在不同的進(jìn)程中。
解決方案:IIS6.0 加入了應(yīng)用程序池 Application Pool 的機(jī)制,為一個(gè)或多個(gè) Web 應(yīng)用創(chuàng)建一個(gè)應(yīng)用程序池,每個(gè)應(yīng)用程序池對(duì)應(yīng)一個(gè)獨(dú)立的工作進(jìn)程 w3wp.exe,所以運(yùn)行在不同應(yīng)用程序池中的 Web 應(yīng)用提供基于進(jìn)程級(jí)別的隔離機(jī)制。
HTTP.SYS
IIS6.0 中最重要的一點(diǎn)是創(chuàng)建了一個(gè)名為 HTTP.SYS 的 HTTP 監(jiān)聽(tīng)器,HTTP.SYS 以驅(qū)動(dòng)程序的形式運(yùn)行在Windows 的內(nèi)核模式 Kernal Mode下,它是 Windows TCP/IP 網(wǎng)絡(luò)子系統(tǒng)的一部分,從結(jié)構(gòu)上看它屬于 TCP 之上的一個(gè)網(wǎng)絡(luò)驅(qū)動(dòng)程序。
嚴(yán)格地說(shuō),HTTP.SYS 已經(jīng)不屬于 IIS 的范疇了,所以 HTTP.SYS 的配置信息也沒(méi)有保存在 IIS 的元數(shù)據(jù)庫(kù)Metabase,而是定義在注冊(cè)表中。HTTP.SYS 的注冊(cè)表項(xiàng)的路徑為HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/HTTP。
HTTP.SYS能夠帶來(lái)如下好處:
- 持續(xù)監(jiān)聽(tīng)
由于 HTTP.SYS 是一個(gè)網(wǎng)路驅(qū)動(dòng)程序,始終處于運(yùn)行狀態(tài),所以對(duì)于用戶(hù)會(huì)的 HTTP 請(qǐng)求能夠及時(shí)作出反應(yīng)。
- 穩(wěn)定性
HTTP.SYS 運(yùn)行在操作系統(tǒng)內(nèi)核模式下,并不執(zhí)行任何用戶(hù)代碼,其本身不會(huì)受到 Web應(yīng)用、工作進(jìn)程、IIS進(jìn)程的影響。
- 內(nèi)核模式下的數(shù)據(jù)緩存
如果某個(gè)資源被頻繁請(qǐng)求,HTTP.SYS 會(huì)把響應(yīng)的內(nèi)容進(jìn)行緩存,緩存的內(nèi)容可直接響應(yīng)后續(xù)的請(qǐng)求。由于這是基于內(nèi)核模式的緩存,不存在內(nèi)核模式和用戶(hù)模式的切換,響應(yīng)速度得到極大的改進(jìn)。
IIS6.0結(jié)構(gòu)
與 IIS5.x 不同,W3SVC 在 IIS6.0 中從 InetInfo.exe 進(jìn)程脫離出來(lái),對(duì)于 IIS6.0 來(lái)說(shuō),InetInfo.exe基本上可以看做單純的 IIS 管理進(jìn)程,運(yùn)行在另一個(gè)進(jìn)程 SvcHost.exe中。不過(guò) W3SVC 的基本功能并沒(méi)有發(fā)生變化,只是在功能的實(shí)現(xiàn)上作出相應(yīng)的改進(jìn)。與 IIS5.x 一樣,元數(shù)據(jù)庫(kù) Metabase 依然存在于InetInfo.exe進(jìn)程中。
IIS6.0與ASP.NET
IIS6.0處理HTTP請(qǐng)求的流程
當(dāng)監(jiān)聽(tīng)到HTTP請(qǐng)求時(shí),HTTP.SYS 將其分發(fā)給 W3SVC,W3SVC 解析出請(qǐng)求的 URL ,并根據(jù)從 Metabase 獲取的 URL 與 Web 應(yīng)用之間的映射關(guān)系得到目標(biāo)應(yīng)用,進(jìn)而得到目標(biāo)應(yīng)用運(yùn)行的應(yīng)用程序池或工作進(jìn)程。如果工作進(jìn)程不存在或尚未創(chuàng)建或被回收,它為請(qǐng)求創(chuàng)建新的工作進(jìn)程。在工作進(jìn)程的初始化過(guò)程中,相應(yīng)的 ISAPI 動(dòng)態(tài)鏈接庫(kù)被加載,對(duì)于 ASP.NET 應(yīng)用來(lái)說(shuō),被加載的 ISAPI.dll 為 aspnet_isapi.dll。ASP.NET ISAPI 負(fù)責(zé)進(jìn)行 CLR 的加載、應(yīng)用程序域的創(chuàng)建和 Web 應(yīng)用的初始化等操作。
IIS7.0與ASP.NET
IIS7.0在請(qǐng)求的監(jiān)聽(tīng)和分發(fā)機(jī)制上進(jìn)行了革新,體現(xiàn)在引入Windows進(jìn)程激活服務(wù)(Windows Process Activation Service, WAS),分流了原來(lái)IIS6.0中W3SVC承載的部分功能。
IIS6.0中的W3SVC主要承載著如下三個(gè)功能:
- HTTP請(qǐng)求接收:接收HTTP.SYS監(jiān)聽(tīng)到的HTTP請(qǐng)求
- 配置管理:從元數(shù)據(jù)Metabase中加載配置信息對(duì)相關(guān)組件進(jìn)行配置
- 進(jìn)程管理:創(chuàng)建、回收、監(jiān)控工作進(jìn)程
IIS7.0將后兩組功能實(shí)現(xiàn)到了WAS中,但接收HTTP請(qǐng)求的任務(wù)依然落在W3SVC上。WAS的引入為IIS7.0提供了對(duì)非HTTP協(xié)議的支持,通過(guò)監(jiān)聽(tīng)適配器接口 Listener Adapter Interface抽象出針對(duì)不同協(xié)議的監(jiān)聽(tīng)器。具體來(lái)說(shuō)或,除了專(zhuān)門(mén)用于監(jiān)聽(tīng)HTTP請(qǐng)求的HTTP.SYS之外,WAS利用TCP監(jiān)聽(tīng)器、命名管道監(jiān)聽(tīng)器和MSMQ監(jiān)聽(tīng)器提供基于TCP、命名管道、MSMQ傳輸協(xié)議的監(jiān)聽(tīng)支持。
與此3種監(jiān)聽(tīng)器相對(duì)應(yīng)的是3種監(jiān)聽(tīng)適配器,它們提供監(jiān)聽(tīng)器與WAS中的監(jiān)聽(tīng)適配器接口之間的適配,從這個(gè)意義上講,IIS7.0中的W3SVC相當(dāng)于HTTP.SYS的監(jiān)聽(tīng)適配器。這3種非HTTP監(jiān)聽(tīng)器和監(jiān)聽(tīng)適配器定義在程序集 SMSvcHost.exe 中??稍谀夸?windir%\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\中找到。
從程序集所在的目錄名稱(chēng)可以看出,這3種監(jiān)聽(tīng)器/監(jiān)聽(tīng)適配器是為WCF設(shè)計(jì)的,它們以Windows服務(wù)的形式進(jìn)行工作。雖然定義在一個(gè)程序集中。但依然可通過(guò)服務(wù)工作管理器對(duì)其進(jìn)行單獨(dú)的啟動(dòng)、終止、配置??偟膩?lái)說(shuō),SMSvcHost.exe提供了4個(gè)重要的Windows Service。
- NetTcpPortSharing
為WCF提供TCP端口共享,即同一個(gè)監(jiān)聽(tīng)端口被多個(gè)進(jìn)程共享。 - NetTcpActivator
為WAS提供基于TCP的激活請(qǐng)求,包含TCP監(jiān)聽(tīng)器和對(duì)應(yīng)的監(jiān)聽(tīng)適配器。 - NetPipeActivator
為WAS提供基于命名管道的激活請(qǐng)求,包含命名管道和對(duì)應(yīng)的監(jiān)聽(tīng)適配器。 - NetMsmqActivator
為WAS提供基于MSMQ的激活請(qǐng)求,包含MSMQ監(jiān)聽(tīng)器和對(duì)應(yīng)的監(jiān)聽(tīng)適配器。
Windows Service
IIS7.0架構(gòu)
IIS7.0與ASP.NET
無(wú)論是從W3SVC接收到的HTTP請(qǐng)求,還是通過(guò)WCF提供的監(jiān)聽(tīng)適配器接收到的針對(duì)其他傳輸協(xié)議的請(qǐng)求,最終都胡被傳遞到WAS。如果相應(yīng)的工作進(jìn)程,針對(duì)單個(gè)應(yīng)用程序池尚未創(chuàng)建,則WAS會(huì)創(chuàng)建工作進(jìn)程。WAS在進(jìn)行請(qǐng)求處理過(guò)程中通過(guò)內(nèi)置的配置管理模塊加載相關(guān)的配置信息,并對(duì)相關(guān)的組件進(jìn)行配置。
與IIS5.x和IIS6.0基于Metabase的配置信息存儲(chǔ)不同的是,IIS7.0大多將配置信息存放在XML形式的配置文件中,基本的配置存放在 applicationHost.config 中。
API.NET 集成
從IIS5.x和IIS6.0中不難發(fā)現(xiàn),IIS與ASP.NET是兩個(gè)獨(dú)立的管道 Pipeline。在各自管轄范圍內(nèi),各自具有自己的一套機(jī)制對(duì)HTTP請(qǐng)求進(jìn)行處理。兩個(gè)管道通過(guò)ISAPI實(shí)現(xiàn)連通。IIS是第一道屏障,當(dāng)對(duì)HTTP請(qǐng)求進(jìn)行必要的前期處理,如身份認(rèn)證等。IIS通過(guò)ISAPI將請(qǐng)求分發(fā)給ASP.NET管道。當(dāng)ASP.NET在自身管道范圍內(nèi)完成對(duì)HTTP請(qǐng)求的處理時(shí),處理后的結(jié)果再返回到IIS,IIS對(duì)其進(jìn)行后期處理,如日志記錄、壓縮等。之后生成HTTP回復(fù)對(duì)請(qǐng)求予以響應(yīng)。
IIS6.0與ASP.NET之間的橋接關(guān)系 基于IIS6.0和ASP.NET雙管道設(shè)計(jì)
從另一個(gè)角度講,IIS運(yùn)行在非托管的環(huán)境中,而ASP.NET管道則是托管的,所以說(shuō)ISAPI是連接非托管環(huán)境和托管環(huán)境的紐帶。IIS5.x和IIS6.0把兩個(gè)管道進(jìn)行隔離帶來(lái)的局限的不足是:
- 相同操作的重復(fù)執(zhí)行
IIS和ASP.NET之間具有一些重復(fù)的操作,如身份驗(yàn)證。
- 動(dòng)態(tài)文件與靜態(tài)文件處理的不一致
因?yàn)橹挥谢贏SP.NET 動(dòng)態(tài)文件的HTTP請(qǐng)求才能通過(guò)ASP.NET ISAPI進(jìn)入ASP.NET管道,對(duì)于靜態(tài)文件的請(qǐng)求則由IIS直接響應(yīng),那么ASP.NET管道中的一些功能將不能作用域這些基于靜態(tài)文件的請(qǐng)求,比如通過(guò)Forms認(rèn)證應(yīng)用于基于圖片文件的請(qǐng)求就做不到。
- IIS難以擴(kuò)展
對(duì)于IIS的擴(kuò)展基本上提現(xiàn)在自定義ISAPI,對(duì)于大部分人來(lái)說(shuō),這不是一件容易的事情,因?yàn)镮SAPI是基于Win32的非托管的API,并非一種面向應(yīng)用的編程接口。通常希望的是諸如定義ASP.NET的HttpModule和HttpHandler一樣,托管代理的方式來(lái)擴(kuò)展IIS。
對(duì)于Windows平臺(tái)下的IIS來(lái)講,ASP.NET無(wú)疑是一等公民,IIS7.0中實(shí)現(xiàn)了兩者的集成,通過(guò)集成可獲得如下好處:
- 允許通過(guò)本地代碼Native Code和托管代碼Managed Code兩種方式定義IIS Module
這些IIS Module注冊(cè)到IIS中形成一個(gè)通用的請(qǐng)求處理管道,由IIS Module組成的這個(gè)管道能夠處理所有的請(qǐng)求,無(wú)論請(qǐng)求基于怎樣的資源類(lèi)型。例如,可將FormAuthenticationModule提供的Forms認(rèn)證應(yīng)用到基于 .aspx、CGI和靜態(tài)文件的請(qǐng)求。
- 將ASP.NET提供的一些強(qiáng)大的功能應(yīng)用到原來(lái)難以企及的地方
比如將ASP.NET的URL重寫(xiě)功能置于身份驗(yàn)證之前
- 采用相同的方式去實(shí)現(xiàn)、配置、檢測(cè)和支持一些服務(wù)器特性 Feature
比如Module、Handler映射、定制錯(cuò)誤配置 Custom Error Configuration 等
基于IIS7.0 與 ASP.NET集成管道設(shè)計(jì)
ASP.NET 管道
以 IIS6.0為例,它的工作進(jìn)程 w3wp.exe 中會(huì)利用 aspnet_isapi.dll 加載 .NET 運(yùn)行時(shí)(如果 .NET 運(yùn)行時(shí)尚未加載)。IIS6.0引入了應(yīng)用程序池的概念,一個(gè)工作進(jìn)程對(duì)應(yīng)著一個(gè)應(yīng)用程序池。一個(gè)應(yīng)用程序池可以承載一個(gè)或多個(gè)Web應(yīng)用,每個(gè)Web應(yīng)用映射到一個(gè)IIS虛擬目錄,與IIS5.x一樣,每個(gè)Web應(yīng)用運(yùn)行在各自的應(yīng)用程序域中。
ASP.NET 處理管道
如果HTTP.SYS接收到的HTTP請(qǐng)求是對(duì)該 Web 應(yīng)用的第一次訪問(wèn),在成功加載運(yùn)行使之后,IIS會(huì)通過(guò) AppDomainFactory 為該Web應(yīng)用創(chuàng)建一個(gè)應(yīng)用程序域。隨后一個(gè)特殊的運(yùn)行時(shí) IsapiRuntime 被加載。IsapiRuntime 定義在程序集 System.Web.dll中,對(duì)應(yīng)的命名空間為System.Web.Hosting, 被加載的 IsapiRuntime 會(huì)接管該HTTP請(qǐng)求。
接管 HTTP 請(qǐng)求的 IsapiRuntime 會(huì)首先創(chuàng)建一個(gè) IsapiWorkerRequest 對(duì)象來(lái)封裝當(dāng)前的HTTP請(qǐng)求,隨后將次對(duì)象傳遞給 ASP.NET 運(yùn)行時(shí) HttpRuntime。從此時(shí)起, HTTP請(qǐng)求正式進(jìn)入了ASP.NET管道。HttpRuntime會(huì)根據(jù) IsapiWorkerRequest 對(duì)象創(chuàng)建用于表示當(dāng)前HTTP請(qǐng)求的上下文 Context 對(duì)象 HttpContext。
隨著 HttpContext 的創(chuàng)建,HttpRuntime 會(huì)利用 HttpApplicationFactory 創(chuàng)建新的或獲取現(xiàn)有的 HttpApplication 對(duì)象。實(shí)際上 ASP.NET 維護(hù)著一個(gè) HttpApplication 對(duì)象池, HttpApplicationFactory 從池中選取可用的 HttpApplication 用于處理 HTTP 請(qǐng)求,處理完畢后將其釋放到對(duì)象池中。HttpApplication 負(fù)責(zé)處理當(dāng)前的 HTTP 請(qǐng)求。
在 HttpApplication 初始化過(guò)程中,ASP.NET 會(huì)根據(jù)配置文件加載并初始化注冊(cè)的 HttpModule 對(duì)象。對(duì)于 HttpApplication 來(lái)說(shuō),在它處理HTTP請(qǐng)求的不同階段會(huì)觸發(fā)不同的事件 Event,而HttpModule的意義在于通過(guò)注冊(cè)HttpApplication的相應(yīng)事件,將所需的操作注入整個(gè)HTTP請(qǐng)求的處理流程。ASP.NET的很多功能都是通過(guò)相應(yīng)的HttpModule實(shí)現(xiàn)的。
最終完成對(duì)HTTP請(qǐng)求的處理實(shí)現(xiàn)在HttpHandler中,不同的資源類(lèi)型對(duì)應(yīng)著不同類(lèi)型的HttpHandler。比如.aspx頁(yè)面對(duì)應(yīng)的HttpHandler類(lèi)型為System.Web.UI.Page,WCF的.svc文件對(duì)應(yīng)的HttpHandler類(lèi)型為System.ServiceModel.Activation.HttpHandler。
HttpApplication
HttpApplication 是整個(gè) ASP.NET 基礎(chǔ)架構(gòu)的核心,負(fù)責(zé)處理分發(fā)給它的HTTP請(qǐng)求。由于一個(gè)HttpApplication對(duì)象在某個(gè)時(shí)刻只能處理一個(gè)請(qǐng)求,只有完成對(duì)某個(gè)請(qǐng)求的處理后才能用于后續(xù)請(qǐng)求的處理,所以ASP.NET采用對(duì)象池的機(jī)制來(lái)創(chuàng)建或獲取 HttpApplication 對(duì)象。
當(dāng)?shù)谝粋€(gè)請(qǐng)求抵達(dá)時(shí),ASP.NET會(huì)一次創(chuàng)建多個(gè)HttpApplication對(duì)象,并將其置于池中,然后選擇其中一個(gè)對(duì)象來(lái)處理該請(qǐng)求。處理完畢后,HttpApplication不會(huì)被回收,而是釋放到池中。對(duì)于后續(xù)的請(qǐng)求,空閑的 HttpApplication 對(duì)象會(huì)從池中取出。如果池中所有的 HttpApplication 對(duì)象都處于繁忙的狀態(tài),在沒(méi)有超出 HttpApplication 池最大容量的情況下,ASP.NET 會(huì)創(chuàng)建新的HttpApplication對(duì)象,否則將請(qǐng)求放入隊(duì)列等待現(xiàn)有HttpApplication的釋放。
HttpApplication 處理請(qǐng)求的整個(gè)生命周期是一個(gè)相對(duì)復(fù)雜的過(guò)程,在該過(guò)程的不同階段會(huì)觸發(fā)相應(yīng)的事件??勺?cè)相應(yīng)的事件,將處理邏輯注入到HttpApplication處理請(qǐng)求的某個(gè)階段。
HttpApplication在處理每個(gè)請(qǐng)求時(shí)觸發(fā)的事件
-
BeginRequest
HTTP管道開(kāi)始處理請(qǐng)求時(shí),會(huì)觸發(fā)BeginRequest事件。 -
AuthenticateRequest, PostAuthenticateRequest
ASP.NET 先后觸發(fā)這兩個(gè)事件,使安全模塊對(duì)請(qǐng)求進(jìn)行身份驗(yàn)證。 -
AuthorizeRequest, PostAuthorizeRequest
ASP.NET先后觸發(fā)這兩個(gè)事件,使安全模塊對(duì)請(qǐng)求進(jìn)行授權(quán)。 -
ResolveRequestCache, PostResolveRequestCache
ASP.NET 先后觸發(fā)這兩個(gè)事件,以使緩存模塊利用緩存的內(nèi)容對(duì)請(qǐng)求直接進(jìn)行響應(yīng)(緩存模塊可將響應(yīng)內(nèi)容進(jìn)行緩存,對(duì)于后續(xù)的請(qǐng)求,直接將緩存的內(nèi)容返回,從而提高響應(yīng)能力。) -
PostMapRequestHandler
對(duì)于訪問(wèn)不同資源類(lèi)型,ASP.NET具有不同的HttpHandler對(duì)其進(jìn)行處理,對(duì)于每個(gè)請(qǐng)求,ASP.NET會(huì)通過(guò)擴(kuò)展名選擇匹配響應(yīng)的HttpHandler類(lèi)型,成功匹配后,該事件被觸發(fā)。 -
AcquireRequestState, PostAcquestRequestState
ASP.NET先后觸發(fā)這兩個(gè)事件,使?fàn)顟B(tài)管理模塊獲取基于當(dāng)前請(qǐng)求相應(yīng)的狀態(tài),如SessionState。 -
PreRequestHandlerExecute、PostRequestHandlerExecute
ASP.NET 最終通過(guò)與請(qǐng)求資源類(lèi)型相對(duì)應(yīng)的 HttpHandler 實(shí)現(xiàn)對(duì)請(qǐng)求的處理,在實(shí)行 HttpHandler 前后,這兩個(gè)事件被先后觸發(fā)。 -
ReleaseRequestState、PostReleaseRequestState
ASP.NET 先后觸發(fā)這兩個(gè)事件,使?fàn)顟B(tài)管理模塊釋放基于當(dāng)前請(qǐng)求響應(yīng)的狀態(tài)。 -
UpdateRequesetCache、PostUpdateRequestCache
ASP.NET先后觸發(fā)這兩個(gè)事件,以使緩存模塊將HttpHandler處理請(qǐng)求得到的內(nèi)容得以保存到輸出緩存中。 -
LogRequest、PostLogRequest
ASP.NET先后觸發(fā)這兩個(gè)事件為當(dāng)前請(qǐng)求進(jìn)行日志記錄 -
EndRequest 整個(gè)請(qǐng)求處理完成后,EndRequest事件會(huì)觸發(fā)。
對(duì)于一個(gè)ASP.NET應(yīng)用來(lái)說(shuō),HttpApplication派生于Global.asax文件,通過(guò)創(chuàng)建Global.asax文件對(duì)HttpApplication的請(qǐng)求處理行為進(jìn)行定制。Global.asax采用一種很直接的方式實(shí)現(xiàn)了這樣的功能,這種方式不是方法重寫(xiě)或事件注冊(cè),而是直接采用方法名匹配。在Global.asax中按照“Application_{Event Name}”的命名規(guī)則進(jìn)行事件注冊(cè)。
?
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing;namespace Huyoo.Backend {// 注意: 有關(guān)啟用 IIS6 或 IIS7 經(jīng)典模式的說(shuō)明,// 請(qǐng)?jiān)L問(wèn) http://go.microsoft.com/?LinkId=9394801public class MvcApplication : System.Web.HttpApplication{protected void Application_Start(){AreaRegistration.RegisterAllAreas();WebApiConfig.Register(GlobalConfiguration.Configuration);FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);RouteConfig.RegisterRoutes(RouteTable.Routes);BundleConfig.RegisterBundles(BundleTable.Bundles);}} }HttpModule
ASP.NET擁有一個(gè)具有高度的可擴(kuò)展的引擎,能處理不同資源類(lèi)型的請(qǐng)求,HttpModule是功不可沒(méi)的。
當(dāng)請(qǐng)求轉(zhuǎn)入ASP.NET管道時(shí),最終負(fù)責(zé)處理該請(qǐng)求的是與請(qǐng)求資源類(lèi)型相匹配的HttpHandler對(duì)象,但是在HttpHandler正式工作之前。ASP.NET會(huì)先加載并初始化所有配置的HttpModule對(duì)象。HttpModule在初始化過(guò)程中,會(huì)將一些回調(diào)操作注冊(cè)到HttpApplication相應(yīng)的事件中。在HttpApplication請(qǐng)求處理生命周期中的某個(gè)階段,相應(yīng)的事件會(huì)被觸發(fā),通過(guò)HttpModule注冊(cè)的事件處理程序也得以執(zhí)行。
所有的HttpModule都實(shí)現(xiàn)了具有如下定義的System.Web.IHttpModule接口,其Init方法實(shí)現(xiàn)了針對(duì)自身的初始化。該方法接受一個(gè)HttpApplication對(duì)象,有了這個(gè)對(duì)象,事件注冊(cè)就很容易了。
?
public interface IHttpModule {void Dispose();void Init(HttpApplication context); }ASP.NET提供了很多基礎(chǔ)功能是通過(guò)相應(yīng)的HttpModule實(shí)現(xiàn)的。除了系統(tǒng)定義的HttpModule之外,可自定義HttpModule,通過(guò) Web.config 可很容易地將其注冊(cè)到 Web 應(yīng)用中。
- OutputCacheModule
實(shí)現(xiàn)了輸出緩存(Output Caching)的功能 - SessionStateModule
在無(wú)狀態(tài)的HTTP協(xié)議上實(shí)現(xiàn)了基于會(huì)話(huà)Session的狀態(tài)保持 - WindowsAuthenticationModule + FormsAuthenticationModule + PassportAuthenticationModule
實(shí)現(xiàn)了Windows、Forms、Passport三種典型的身份認(rèn)證方式 - UrlAuthorizationModule + FileAuthorizationModule
實(shí)現(xiàn)了基于URL和文件ACL(Access Control List)的授權(quán)
HttpHandler
對(duì)于不同資源類(lèi)型的請(qǐng)求,ASP.NET會(huì)加載不同的Handler來(lái)處理,比如.aspx頁(yè)面與.asmx Web服務(wù)對(duì)應(yīng)的Handler是不同的。
所有的HttpHandler都實(shí)現(xiàn)了具有如下定義的接口 System.Web.IHttpHandler,定義其中的方法ProcessRequest提供了處理請(qǐng)求的實(shí)現(xiàn)。
另一個(gè)代表異步版本的HttpHandler的IHttpAsyncHandler接口繼承自IHttpHandler,它通過(guò)調(diào)用BeginProcessRequest/EndProcessRequest方法以異步的方式處理請(qǐng)求。
?
public interface IHttpHandler {void ProcessRequest(HttpContext context);bool IsReusable{ get; } } public interface IHttpAsyncHandler:IHttpHandler {IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData);void EndProcessRequest(IAsyncResult result); }某些 HttpHandler 具有一個(gè)與之相關(guān)的HttpHandlerFactory,后者實(shí)現(xiàn)了具有如下定義的接口 System.Web.IHttpHandlerFactory,定義其中的方法GetHandler用于創(chuàng)建新的HttpHandler或獲取已經(jīng)存在的HttpHandler。
?
public interface IHttpHandlerFactory {IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTransslated);void ReleaseHandler(IHttpHandler handler); }HttpHandler和HttpHandlerFactory的類(lèi)型都可以通過(guò)相同的方式配置到 Web.config中。
在調(diào)用當(dāng)前HttpContext的RemapHandler方法時(shí)指定一個(gè)具體的HttpHandler對(duì)象,是為了讓ASP.NET直接跳過(guò)默認(rèn)的HttpHandler映射操作。此外,由于這個(gè)默認(rèn)的HttpHandler映射發(fā)生在HttpApplication的PostMapRequestHandler事件觸發(fā)之前,所以只有在這之前調(diào)用RemapHandler方法才有意義。
作者:JunChow520
鏈接:https://www.jianshu.com/p/85c7c931a3e7
來(lái)源:簡(jiǎn)書(shū)
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
總結(jié)
以上是生活随笔為你收集整理的IIS/ASP.NET 管道的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: iPhone 14上热搜!供应链称已全系
- 下一篇: ASP.NET Core管道深度剖析[共