作為一個Asp.Net平台開發者,非常有必要了解IIS和Asp.Net是如何結合,執行我們的托管代碼,以及Asp.Net管道事件的.
本節目錄
InetInfo.exe與W3SVC服務
IIS 5.x運行在進程InetInfo.exe中,在該進程中一個最重要的服務就是名為World Wide Web Publishing Service(簡稱W3SVC)的Windows Service。
W3SVC的主要功能包括HTTP請求的監聽、工作進程的管理以及配置管理(通過從Metabase中加載相關配置信息)等。
請求資源(根據擴展名區分靜態和動態資源)
靜態文件,直接返回文件內容。
動態資源,通過擴展名從IIS的腳本影射(Script Map)找到相應的ISAPI Dll。
ISAPI
ISAPI是Internet服務器API(Internet Server Application Programming Interface)的縮寫.是IIS和其他應用的紐帶.
ISAPI包括ISAPI Extension和ISAPI Filter
ISAPI Extension
不用種類的動態資源,會有不同的ISAPI擴展.
如Asp.Net(.aspx .asmx .svc等)則為aspnet_isapi.dll。在目錄“%windir%\Microsoft.NET\Framework\{version no}\”中找到該dll。
ISAPI Filter
Filter則可以在HTTP請求真正被處理之前查看、修改、轉發或者拒絕請求,比如IIS可以利用ISAPI篩選進行請求的驗證(Authentication)。
請求Asp.Net
如果我們請求的是一個基於ASP.NET的資源:
- 加載aspnet_isapi.dll
- 創建工作進程(第一次請求)
- 加載CLR(第一次請求)
- 創建AppDomain(某個web應用的第一次請求)
- 執行ISAPIRuntime.


說明:
- 對於IIS 5.x來說,該工作進程為aspnet_wp.exe。
- aspnet_isapi.dll與工作進程之間通過命名管道(Named Pipes)進程通信,以獲得最好的性能。
- 對於寄宿於IIS 5.x的所有Web 應用都運行在同一個工作進程的不同AppDomain中。
IIS5的不足
- aspnet_isapi與工作進程之間是跨進程通信。
- 所有的web應用都是在同一個工作進程中。
IIS6解決辦法
- 將aspnet_ispai.dll加載到工作進程中。
- 建立應用程序池,一個應用程序池對應一個工作進程。
另外在IIS6中,創建新的http監聽器:HTTP協議棧(HTTP Protocol Stack,HTTP.SYS)
- 持續監聽:由於HTTP.SYS是一個網絡驅動程序,始終處於運行狀態,對於用戶的HTTP請求,能夠及時作出反應;
- 更好的穩定性:HTTP.SYS運行在操作系統內核模式下,並不執行任何用戶代碼,所以其本身不會受到Web應用、工作進程和IIS進程的影響;
- 內核模式下數據緩存:如果某個資源被頻繁請求,HTTP.SYS會把響應的內容進行緩存,緩存的內容可以直接響應后續的請求。由於這是基於內核模式的緩存,不存在內核模式和用戶模式的切換,響應速度將得到極大的改進。
請求Asp.Net
與IIS5.X不同的是:
1.W3SVC服務根據請求創建工作進程
2.aspnet_isapi.dll是在工作進程的初始化過程中被加載。
說明:
- W3SVC服務已經從iis進程中脫離出來。http.sys接受到請求,將直接分發給w3svc服務
- 在IIS6中工作進程名為w3wp.exe
- 工作進程的這種創建方式被稱為請求式創建
W3SVC服務

在IIS6中的W3SVC服務的功能
- HTTP請求接收:接收HTTP.SYS監聽到的HTTP請求;
- 配置管理:從元數據庫(Metabase)中加載配置信息對相關組件進行配置;
- 進程管理:創建、回收、監控工作進程。
在IIS7中W3SVC只負責第一個功能,剩余功能交給WAS服務管理
WAS服務

IIS7引入Windows進程激活服務(Windows Process Activation Service,WAS):同時處理HTTP和非HTTP請求。
在WAS中,定義了一個重要的接口:監聽器適配器接口(Listener Adapter Interface)抽象出不同協議監聽器監聽到的請求。
WAS將監聽W3SVC服務的http請求以及WCF服務的TCP、Named Pipes、MSMQ3種請求.

說明
WCF提供的這3種監聽器和監聽適配器定義在程序集SMHost.exe中,你可以通過下面的目錄找到該程序集:%windir%\Microsoft.NET\Framework\v3.0\Windows Communication Foundation。
SMHost.exe提供了4個重要的Windows Service:
- NetTcpPortSharing:為WCF提供TCP端口共享,關於端口共享;
- NetTcpActivator:為WAS提供基於TCP的激活請求,包含TCP監聽器和對應的監聽適配器;
- NetPipeActivator:為WAS提供基於命名管道的激活請求,包含命名管道監聽器和對應的監聽適配器;
- NetMsmqActivator:為WAS提供基於MSMQ的激活請求,包含MSMQ監聽器和對應的監聽適配器。
傳統模式的缺點
- 相同操作的重復執行:IIS與ASP.NET之間具有一些重復的操作,比如身份驗證;
- 動態文件與靜態文件處理的不一致:因為只有基於ASP.NET的動態文件(比如.aspx、.asmx、.svc等等)的HTTP請求才能通過ASP.NET ISAPI進入ASP.NET管道,而對於一些靜態文件(比如.html、.xml、.img等)的請求,則由IIS直接響應,那么ASP.NET管道中的一些功能將不能用於這些基於靜態文件的請求,比如,我們希望通過Forms認證應用於基於圖片文件的請求;
- IIS難以擴展:對於IIS的擴展基本上就體現在自定義ISAPI,但是對於大部分人來說,這不是一件容易的事情。因為ISAPI是基於Win32的非托管的API,並非一種面向應用的編程接口。通常我們希望的是諸如定義ASP.NET的HttpModule和HttpHandler一樣,通過托管代碼的方式來擴展IIS。
集成模式

實際上IIS7集成模式,就是讓用戶可以通過編寫托管代碼的module,把托管代碼插入到IIS內核代碼中來解析,方便大家精確控制任意請求,帶來更好的擴展性。
(這里面每個靜態文件也會經過生命周期事件,執行效率肯定會有所下降.)
配置文件上的區別
<!--傳統模式-->
<system.web>
<customErrors mode="RemoteOnly">
<error statusCode="404" redirect="404.html"/>
<error statusCode="500" redirect="500.html"/>
</customErrors>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<!--集成模式-->
<system.webServer>
<httpErrors errorMode="DetailedLocalOnly">
<clear/>
<error path="404.html" statusCode="404"/>
<error path="500.html" statusCode="500"/>
</httpErrors>
</system.webServer>
- 加載CLR:在工作進程中,ISAPI負責進行CLR的加載(如果.NET運行時尚未加載).
- 創建AppDomain:當成功加載了運行時后,會通過AppDomainFactory為該Web應用創建一個應用程序域(AppDomain)。
- 執行ISAPIRuntime的int ProcessRequest(IntPtr ecb, int iWRType)方法
- 執行HttpRuntime的PR方法

- 獲取httpapplication實例,調用httpapplication的pr方法

- 觸發httpapplication各事件.
擴展
- 在HttpApplication初始化過程中,會根據配置文件加載並初始化相應的HttpModule對象。對於HttpApplication來說,在它處理HTTP請求的不同的階段會觸發不同的事件(Event),而HttpModule的意義在於通過注冊HttpApplication的相應的事件,將所需的操作注入整個HTTP請求的處理流程。ASP.NET的很多功能,比如身份驗證、授權、緩存等,都是通過相應的HttpModule實現的。
- 而最終完成對HTTP請求的處理實現在另一個重要的對象中:HttpHandler。對於不同的資源類型,具有不同的HttpHandler。比如.aspx頁對應的HttpHandler為System.Web.UI.Page,WCF的.svc文件對應的HttpHandler為System.ServiceModel.Activation.HttpHandler。
- 對於一個ASP.NET應用來說,HttpApplication派生於global.asax文件,我們可以通過創建global.asax文件對HttpApplication的請求處理行為進行定制。global.asax采用一種很直接的方式實現了這樣的功能,這種方式既不是我們常用的方法重寫(Method Overriding)或者事件注冊,而是直接采用方法名匹配。在global.asax中,我們按照這樣的方法命名規則進行事件注冊:Application_{Event Name}。比如Application_BeginRequest方法用於處理HttpApplication的BeginRequest事件。
從功能上講,HttpModule之於ASP.NET,就好比ISAPI Filter之於IIS一樣。IIS將接收到的請求分發給相應的ISAPI Extension之前,注冊的ISAPI Filter會先截獲該請求。
如果說HttpModule相當於IIS的ISAPI Filter的話,我們可以說HttpHandler則相當於IIS的ISAPI Extension,HttpHandler在ASP.NET中扮演請求的最終處理者的角色。
當請求轉入ASP.NET管道后,最終負責處理該請求的是與請求資源類型相匹配的HttpHandler對象,但是在Handler正式工作之前,ASP.NET會先加載並初始化所有配置的HttpModule對象。HttpModule在初始化的過程中,會將一些功能注冊到HttpApplication相應的事件中,那么在HttpApplication整個請求處理生命周期中的某個階段,相應的事件會被觸發,通過HttpModule注冊的事件處理程序也得以執行。
所有的HttpModule都實現了IHttpModule接口.
namespace System.Web
{
public interface IHttpModule
{
void Init(HttpApplication context);
void Dispose();
}
}
系統定義的HttpModule
- OutputCacheModule:實現了輸出緩存(Output Caching)的功能;
- SessionStateModule:在無狀態的HTTP協議上實現了基於會話(Session)的狀態;
- WindowsAuthenticationModule + FormsAuthenticationModule:實現了3種典型的身份認證方式:Windows認證、Forms認證;
- WCFModule:使Asp.Net擴展出WCF服務(System.ServiceModel.Activation.HttpModule)
自定義HttpMoudle
- 實現IHttpMoudle
- 修改配置文件Web.config
對於不同資源類型的請求,ASP.NET會加載不同的Handler來處理,也就是說.aspx page與.asmx web service對應的Handler是不同的。
所有的HttpHandler都實現了接口IHttpHandler。
public interface IHttpHandler
{
bool IsReusable { get; }
void ProcessRequest(HttpContext context);
}
系統定義的HttpHandle
WebForm的aspx文件:System.Web.UI.Page
WCF的svc文件:System.ServiceModel.Activation.HttpHandler
MVC:MVCHandler
自定義HttpHandle
由於Handle是在PostMapRequestHandler前和 PostResolveRequestCache 后映射指定的Handle,
所以我們可以在PostResolveRequestCache事件中注冊我們的Handle.
在PreRequestHandlerExecute 后將會調用我們的Handle.PR方法.
擴展
HttpApplication主要有19個事件,通過我的網站任意地址+參數即可訪問所有事件。
+?pipe可以查看這些事件觸發時間.如:http://neverc.cn?pipe
+?pe可以附帶我的網站內容:http://neverc.cn?pe
猜猜如何實現出以上效果
本文地址:http://neverc.cnblogs.com/p/4807836.html
本文參考: http://www.cnblogs.com/artech/archive/2009/06/20/1507165.html
