- 相關(guān)推薦
ASPNET是怎樣在IIS下工作的
ASP.NET與IIS是緊密聯(lián)系的,由于IIS6.0與IIS7.0的工作方式的不同,導(dǎo)致ASP.NET的工作原理也發(fā)生了相應(yīng)的變化。
IIS6(IIS7的經(jīng)典模式)與IIS7的集成模式的不同
IIS6的運(yùn)行過(guò)程:
分析上圖可知:
在 User Mode 下,http.sys 接收到 http request,然后它會(huì)根據(jù) IIS 中的 Metabase 查看基于該 Request 的 Application 屬于哪個(gè) Application Pool, 如果該 Application Pool 不存在,則創(chuàng)建之。否則直接將 request 發(fā)到對(duì)應(yīng) Application Pool 的 Queue中。每個(gè) Application Pool 對(duì)應(yīng)著一個(gè) Worker Process — w3wp.exe,(運(yùn)行在 User Mode 下)。
在 IIS Metabase 中維護(hù)著 Application Pool 和 Worker Process 的Mapping。WAS(Web Administrative Service)根據(jù)這樣一個(gè) mapping,將存在于某個(gè) Application Pool Queue 的 request 傳遞到對(duì)應(yīng)的 Worker Process (如果沒有,就創(chuàng)建這樣一個(gè)進(jìn)程)。在 Worker Process 初始化的時(shí)候,加載 ASP.NET ISAPI,ASP.NET ISAPI 進(jìn)而加載 CLR。最后通過(guò) AppManagerAppDomainFactory 的 Create 方法為 Application 創(chuàng)建一個(gè) Application Domain;通過(guò) ISAPIRuntime 的 ProcessRequest 處理 Request,進(jìn)而將流程進(jìn)入到 ASP.NET Http Runtime Pipeline。
幾個(gè)知識(shí)點(diǎn):
HTTP.SYS:(Kernel)的一個(gè)組件,它負(fù)責(zé)偵聽(Listen)來(lái)自于外部的HTTP請(qǐng)求,根據(jù)請(qǐng)求的URL將其轉(zhuǎn)發(fā)給相應(yīng)的應(yīng)用程序池 (Application Pool)。當(dāng)此HTTP請(qǐng)求處理完成時(shí),它又負(fù)責(zé)將處理結(jié)果發(fā)送出去.為了提供更好的性能,HTTP.SYS內(nèi)部建立了一個(gè)緩沖區(qū),將最近的HTTP請(qǐng)求處理結(jié)果保存起來(lái)。
Application Pool: IIS總會(huì)保持一個(gè)單獨(dú)的工作進(jìn)程:應(yīng)用程序池。所有的處理都發(fā)生在這個(gè)進(jìn)程里,包括ISAPI dll的執(zhí)行。對(duì)于IIS6而言,應(yīng)用程序池是一個(gè)重大的改進(jìn),因?yàn)樗鼈冊(cè)试S以更小的粒度控制一個(gè)指定進(jìn)程的執(zhí)行。你可以為每一個(gè)虛擬目錄或者整個(gè)Web 站點(diǎn)配置應(yīng)用程序池,這可以使你很容易的把每一個(gè)應(yīng)用程序隔離到各自的進(jìn)程里,這樣就可以把它與運(yùn)行在同一臺(tái)機(jī)器上其他程序完全隔離。從Web處理的角度看,如果一個(gè)進(jìn)程死掉,至少它不會(huì)影響到其它的進(jìn)程。
當(dāng)應(yīng)用程序池接收到HTTP請(qǐng)求后,交由在此應(yīng)用程序池中運(yùn)行的工作者進(jìn)程Worker Process: w3wp.exe來(lái)處理此HTTP請(qǐng)求。
Worker Process: 當(dāng)工作者進(jìn)程接收到請(qǐng)求后,首先根據(jù)后綴找到并加載對(duì)應(yīng)的ISAPI擴(kuò)展 (如:aspx 對(duì)應(yīng)的映射是aspnet_isapi.dll),工作者進(jìn)程加載完aspnet_isapi.dll后,由aspnet_isapi.dll負(fù)責(zé)加載 ASP.NET應(yīng)用程序的運(yùn)行環(huán)境即CLR (.NET Runtime)。
Worker Process運(yùn)行在非托管環(huán)境,而.NET中的對(duì)象則運(yùn)行在托管環(huán)境之上(CLR),它們之間的橋梁就是ISAPI擴(kuò)展。
WAS(Web Admin Service):這是一個(gè)監(jiān)控程序,它一方面可以存取放在InetInfo元數(shù)據(jù)庫(kù)(Metabase)中的各種信息,另一方面也負(fù)責(zé)監(jiān)控應(yīng)用程序池(Application Pool)中的工作者進(jìn)程的工作狀態(tài)況,必要時(shí)它會(huì)關(guān)閉一個(gè)老的工作者進(jìn)程并創(chuàng)建一個(gè)新的取而代之。
IIS7的運(yùn)行過(guò)程:
分析上圖可知:
1、當(dāng)客戶端瀏覽器開始 HTTP 請(qǐng)求一個(gè)WEB 服務(wù)器的資源時(shí),HTTP.sys 攔截到這個(gè)請(qǐng)求。
2、HTTP.sys 聯(lián)系 WAS 獲取配置信息。
3、WAS 向配置存儲(chǔ)中心(applicationHost.config)請(qǐng)求配置信息。
4、WWW 服務(wù)接收到配置信息,配置信息指類似應(yīng)用程序池配置信息,站點(diǎn)配置信息等等。
5、WWW 服務(wù)使用配置信息去配置 HTTP.sys 處理策略。
6、WAS為請(qǐng)求創(chuàng)建一個(gè)進(jìn)程(如果不存在的話)。
7、工作者進(jìn)程處理請(qǐng)求并對(duì)HTTP.sys做出響應(yīng)。
8、客戶端接受到處理結(jié)果信息。
除了IIS的整體運(yùn)行方式不同之外,IIS7相比IIS6最大的不同之處在于它提供了兩種應(yīng)用程序池管道模式:
經(jīng)典模式:是與IIS 6或者之前版本保持兼容的一種模式,一個(gè)典型問(wèn)題就是,在處理ASP.NET這種動(dòng)態(tài)網(wǎng)站的時(shí)候,它是通過(guò)一個(gè)所謂的ISAPI程序,作為插件的方式來(lái)工作的。針對(duì)不同的動(dòng)態(tài)應(yīng)用程序(例如ASP,PHP等),會(huì)需要不同的ISAPI(Internet Server Application Programe Interface,互聯(lián)網(wǎng)服務(wù)器應(yīng)用程序接口)。如圖,在IIS中,打開“處理程序映射”,可以看到aspx類型頁(yè)面的處理程序?yàn)閍spnet_isapi.dll。
下圖展示了IIS7經(jīng)典模式與IIS6的應(yīng)用程序池管道模式運(yùn)行原理,針對(duì)不同的請(qǐng)求,會(huì)指定不同的ISAPI(dll)進(jìn)行處理:
集成模式:asp.net不再像IIS6一樣只限定于aspnet_isapi.dll中,而是被解放出來(lái),從IIS接收到HTTP請(qǐng)求開始,即進(jìn)入asp.net的控制范圍,asp.net可以存在于一個(gè)請(qǐng)求在IIS中各個(gè)處理階段。允許我們將ASP.NET更好地與IIS集成,甚至允許我們?cè)贏SP.NET中編寫一些功能(例如Module)來(lái)改變IIS的行為(擴(kuò) 展)。集成的好處是,不再通過(guò)ISAPI的方式,提高了速度和穩(wěn)定性。至于擴(kuò)展,則可以使得我們對(duì)于IIS,以及其他類型的請(qǐng)求有更多的控制。(例如,我 們希望靜態(tài)網(wǎng)頁(yè)也具備一些特殊的行為)。如圖
如下圖在IIS7集成模式中,打開處理程序映射,可以看到aspx類型頁(yè)面所對(duì)應(yīng)的不再是一個(gè)dll,而是一個(gè)類型。
總結(jié)與擴(kuò)展:
對(duì)于處理ASP.NET應(yīng)用程序而言,IIS6及IIS7的經(jīng)典模式需要aspnet_isapi.dll來(lái)處理,而IIS7集成模式不需要aspnet_isapi.dll來(lái)處理,而可以直接根據(jù)文件擴(kuò)展名找到相應(yīng)的處理程序接口。例如aspx的處理程序是System.Web.UI.PageHandlerFactory類型。
介紹完IIS的工作原理,來(lái)看一下ASP.NET內(nèi)部的運(yùn)行機(jī)制。
首先看一下IIS處理模型:
上面介紹IIS工作原理時(shí),已經(jīng)介紹了從發(fā)起HTTP請(qǐng)求,到響應(yīng)請(qǐng)求的過(guò)程,這里主要介紹當(dāng)請(qǐng)求到達(dá).NET Runtime之后,.NET運(yùn)行時(shí)所發(fā)生的一系列工作。
先看如下的.NET運(yùn)行時(shí)工作序列圖:
1.HTTP請(qǐng)求進(jìn)入Web服務(wù)器后,首先由HTTP.SYS來(lái)判斷請(qǐng)求的頁(yè)面是否存在,如果存在的話將把請(qǐng)求信息轉(zhuǎn)交給.NET Runtime。在這部分實(shí)際是完成兩個(gè)步驟,在將請(qǐng)求轉(zhuǎn)交給.NET Runtime的同時(shí)將請(qǐng)求信息封存在HTTPWorkRequest類中供其它步驟調(diào)用。HttpWorkRequest類在以后的操作中至關(guān)重要,它第一次將Http請(qǐng)求信息轉(zhuǎn)換為類信息。
2.當(dāng)請(qǐng)求到達(dá).NET Runtime后,接下來(lái)的操作將會(huì)在托管環(huán)境中完成,這時(shí)請(qǐng)求就真正進(jìn)入了.NET中,對(duì)請(qǐng)求信息的操作是由.NET的底層類庫(kù)來(lái)實(shí)現(xiàn)。首先.NET Runtime將會(huì)針對(duì)請(qǐng)求信息做兩個(gè)動(dòng)作,一是準(zhǔn)備HostingEnvironment;二是調(diào)用ApplicationManager類為HTTP請(qǐng)求動(dòng)態(tài)的分配AppDomain,并把處理權(quán)交給AppDomain。
3.HTTP請(qǐng)求進(jìn)入AppDomain后,將由對(duì)象ISAPIRuntime來(lái)接管,一方面經(jīng)方法ProcessRequest()得到HttpWorkerRequest對(duì)象,另一方面由方法StartProcessing()生成HttpRuntime對(duì)象,接下來(lái)把處理權(quán)交給了HttpRuntime(HttpWorkerRequest對(duì)象將作為HttpRuntime方法中的參數(shù)被使用)。
4.HTTPRuntime接收到Http請(qǐng)求后,方法ProcessRequest處理請(qǐng)求。將對(duì)第1步中的HTTPWorkRequest類中的信息進(jìn)行操作,具體的實(shí)現(xiàn)由ProcessRequest方法實(shí)現(xiàn)。內(nèi)部代碼如下:
[AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)]public static void ProcessRequest(HttpWorkerRequest wr){if (wr == null){throw new ArgumentNullException("wr");}if (UseIntegratedPipeline){throw new PlatformNotSupportedException(System.Web.SR.GetString("Method_Not_Supported_By_Iis_Integrated_Mode", new object[] { "HttpRuntime.ProcessRequest" }));}ProcessRequestNoDemand(wr);}internal static void ProcessRequestNoDemand(HttpWorkerRequest wr){RequestQueue queue = _theRuntime._requestQueue;if (queue != null){wr = queue.GetRequestToExecute(wr);}if (wr != null){CalculateWaitTimeAndUpdatePerfCounter(wr);wr.ResetStartTime();ProcessRequestNow(wr);}}internal static void ProcessRequestNow(HttpWorkerRequest wr){_theRuntime.ProcessRequestInternal(wr);}
5.在HttpRunTime中經(jīng)過(guò)一系列的驅(qū)動(dòng)后,將會(huì)在ProcessRequestInternal方法中為Http請(qǐng)求分配應(yīng)用程序。在這一步中還將創(chuàng)建HttpContext對(duì)象。
context = new HttpContext(wr, false); // 基于HttpWorkerRequest生成HttpContextIHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context); // 得到HttpApplicationhandler2.BeginProcessRequest(context, this._handlerCompletionCallback, context); // 由HttpApplication處理請(qǐng)求
6.經(jīng)過(guò)步驟5后HTTP請(qǐng)求信息才由基本信息轉(zhuǎn)交給了Asp.net中的各個(gè)對(duì)象。接下來(lái)的操作會(huì)觸發(fā)一些列的管道事件,這時(shí)的請(qǐng)求才真正轉(zhuǎn)到HttpModule和HttpHandler中。
接下來(lái)我們看看常說(shuō)的管道事件的創(chuàng)建過(guò)程:
internal override void BuildSteps(WaitCallback stepCallback){ArrayList steps = new ArrayList();HttpApplication app = base._application;bool flag = false;UrlMappingsSection urlMappings = RuntimeConfig.GetConfig().UrlMappings;flag = urlMappings.IsEnabled && (urlMappings.UrlMappings.Count > 0);steps.Add(new HttpApplication.ValidatePathExecutionStep(app));if (flag){steps.Add(new HttpApplication.UrlMappingsExecutionStep(app));}app.CreateEventExecutionSteps(HttpApplication.EventBeginRequest, steps);app.CreateEventExecutionSteps(HttpApplication.EventAuthenticateRequest, steps);app.CreateEventExecutionSteps(HttpApplication.EventDefaultAuthentication, steps);app.CreateEventExecutionSteps(HttpApplication.EventPostAuthenticateRequest, steps);app.CreateEventExecutionSteps(HttpApplication.EventAuthorizeRequest, steps);app.CreateEventExecutionSteps(HttpApplication.EventPostAuthorizeRequest, steps);app.CreateEventExecutionSteps(HttpApplication.EventResolveRequestCache, steps);app.CreateEventExecutionSteps(HttpApplication.EventPostResolveRequestCache, steps);steps.Add(new HttpApplication.MapHandlerExecutionStep(app));app.CreateEventExecutionSteps(HttpApplication.EventPostMapRequestHandler, steps);app.CreateEventExecutionSteps(HttpApplication.EventAcquireRequestState, steps);app.CreateEventExecutionSteps(HttpApplication.EventPostAcquireRequestState, steps);app.CreateEventExecutionSteps(HttpApplication.EventPreRequestHandlerExecute, steps);steps.Add(new HttpApplication.CallHandlerExecutionStep(app)); //調(diào)用HttpHandlerapp.CreateEventExecutionSteps(HttpApplication.EventPostRequestHandlerExecute, steps);app.CreateEventExecutionSteps(HttpApplication.EventReleaseRequestState, steps);app.CreateEventExecutionSteps(HttpApplication.EventPostReleaseRequestState, steps);steps.Add(new HttpApplication.CallFilterExecutionStep(app));app.CreateEventExecutionSteps(HttpApplication.EventUpdateRequestCache, steps);app.CreateEventExecutionSteps(HttpApplication.EventPostUpdateRequestCache, steps);this._endRequestStepIndex = steps.Count;app.CreateEventExecutionSteps(HttpApplication.EventEndRequest, steps);steps.Add(new HttpApplication.NoopExecutionStep());this._execSteps = new HttpApplication.IExecutionStep[steps.Count];steps.CopyTo(this._execSteps);this._resumeStepsWaitCallback = stepCallback;}
管道事件請(qǐng)求序列圖如下:
【ASPNET是怎樣在IIS下工作的】相關(guān)文章:
怎樣快樂(lè)的工作10-05
怎樣積極的工作09-08
則怎樣做好信貸工作08-16
怎樣消除工作疲勞08-08
學(xué)會(huì)怎樣更好的工作09-20
怎樣解決工作負(fù)能量09-07
怎樣開展德育工作06-22