ASP.NET Core管道深度剖析(1):采用管道处理HTTP请求
之所以稱ASP.NET Core是一個Web開發(fā)平臺,源于它具有一個極具擴展性的請求處理管道,我們可以通過這個管道的定制來滿足各種場景下的HTTP處理需求。ASP. NET Core應(yīng)用的很多特性,比如路由、認證、會話、緩存等,也同時定制消息處理管道來實現(xiàn)的。我們甚至可以通過管道定制在ASP.NET Core平臺上創(chuàng)建我們自己的Web框架,實際上MVC和SingalR這兩個重要的Web框架也是采用這樣的方式創(chuàng)建的。
HTTP協(xié)議自身的特性決定了任何一個Web應(yīng)用的工作方式都是監(jiān)聽、接收并處理HTTP請求,并在最終對請求予以響應(yīng),HTTP請求處理是管道式設(shè)計典型的應(yīng)用場景。我們根據(jù)HTTP請求的處理流程定制出一個消息處理管道,讓接收到的HTTP請求消息想水一樣流入這個管道,組成這個管道的各個環(huán)節(jié)一次對它作相應(yīng)的處理。處理的結(jié)果同樣轉(zhuǎn)變成消息逆向流入這個管道進行處理,并最終轉(zhuǎn)變成回復(fù)給客戶端的HTTP響應(yīng)。ASP.NET Core的消息處理管道從設(shè)計的角度來講是非常簡單的,但是從具體實現(xiàn)的角度則相對難以理解,為了讓讀者朋友們通過本章對此具有深刻的理解,我們從簡單的部分講起。
一、從Hello World說起
為了使讀者朋友們能夠以最直觀的感受認識ASP.NET Core的消息處理管道,我們來創(chuàng)建一個最簡單的Hello World程序。這是一個僅僅由兩個類型構(gòu)成的控制臺程序,作為程序入口的Main方法定義在Program類中,Startup則作為初始化類型。這個程序被啟動之后將會綁定到默認端口5000進行HTTP請求的監(jiān)聽,任何針對基地址 “http://localhost:5000/” 的請求后,該程序都將響應(yīng) “Hello World” 。
1: class Program 2: { 3: static void Main(string[] args) 4: { 5: new WebHostBuilder() 6: .UseKestrel() 7: .UseStartup<Startup> 8: .Build() 9: .Start(); 10: } 11: } 12:? 13: 14: public class Startup 15: { 16: public void Configure(IApplicationBuilder app) 17: { 18: app.Run(context=>context.Response.WriteAsync("Hello World"); 19: } 20: }這個程序涉及到一個重要的對象WebHost,它通過WebHostBuilder的Build方法創(chuàng)建。WebHost可以看成是Web應(yīng)用的宿主,啟動Web應(yīng)用本質(zhì)上就是啟動它的宿主。當我們調(diào)用WebHost的Start方法啟動應(yīng)用的時候,用于監(jiān)聽、接收、處理和響應(yīng)HTTP請求的消息處理管道隨之被建立。那么在這個過程中,通過調(diào)用UseStartup<T>方法注冊到WebHostBuilder上的初始化類型將用來對這個管道進行定制。總的來說,ASP.NET Core的請求處理管道由WebHost在啟動的時候構(gòu)建,WebHostBuilder則是后者的創(chuàng)建者,右圖揭示了三者之間的關(guān)系。
二、管道的構(gòu)成
HTTP請求處理流程始于對請求的監(jiān)聽與接收,終于對請求的響應(yīng),這兩項工作由同一個對象來完成,我們稱之為 “服務(wù)器(Server)” ,盡管ASP.NET Core的請求處理管道可以被自由地訂制,但是該管道必須有一個服務(wù)器,服務(wù)器是整個管道的 “龍頭” 。在上面的這個Hello World應(yīng)用中,在調(diào)用WebHostBuilder的Build方法創(chuàng)建一個WebHost之前,我們調(diào)用了它的一個擴展方法UseKestrel,這個方法的作用就是為后續(xù)構(gòu)建的管道注冊一個名為KestrelServer的服務(wù)器。
隨著WebHost的Start方法的調(diào)用,按照具體需求進行定制的請求處理管道被構(gòu)建出來,作為第一個節(jié)點的服務(wù)器會綁定到一個預(yù)設(shè)的端口(比如KestrelServer默認采用5000作為監(jiān)聽端口)開始監(jiān)聽來自客戶端的HTTP請求。一旦請求抵達,服務(wù)器會接收請求并將其標準化后向管道后續(xù)的節(jié)點進行轉(zhuǎn)發(fā),我們將管道中位于服務(wù)器之后的請求處理節(jié)點成為“中間件(Middleware)”。每個中間件都具有各自獨立的功能,比如我們有專門實現(xiàn)路由功能的中間件,由專門實施用戶認證的中間,所謂的對請求處理管道的定制體現(xiàn)在根據(jù)具體的需求選擇對應(yīng)的中間件組成最終處理請求的管道。左圖揭示了由一個服務(wù)器和一組中間件構(gòu)成的請求處理管道。
一個建立在ASP.NET Core之上的應(yīng)用一般都是根據(jù)某個框架開發(fā)的,開發(fā)框架基本上是建立在某個特殊的中間件上。以ASP.NET Core MVC這個最著名的框架為例,它實際上是利用一個叫做 “路由” 的中間件實現(xiàn)了請求地址與Controller/Action之間的映射,并在此基礎(chǔ)實現(xiàn)了激活Controller、執(zhí)行Action以及呈現(xiàn)View等一系列的功能。所以應(yīng)用程序可以視為某個中間件的一部分,如果一定要將它獨立出來,整個請求處理管道將呈現(xiàn)出如右圖所示的結(jié)構(gòu)。
三、管道的定制
在演示的Hello World程序中,我們在調(diào)用WebHostBuilder的Build方法創(chuàng)建WebHost之前先調(diào)用了它的擴展方法UseStartup<T>方法注冊了一個類型為Startup的啟動類型。從請求處理管道的角度來講,注冊的這個啟動類型的目的在于對構(gòu)建的管道進行定制,說得更加具體一點,我們利用這個類型為管道注冊需要的中間件。一般來說,被注冊的啟動類型必須具有一個類似于下面代碼片斷所示的Configure方法,這個方法可以是靜態(tài)方法和也可以實例方法。這個方法的參數(shù)并沒有嚴格的限制,但是第一個參數(shù)類型必須是IApplicationBuilder接口。
1: public class Startup 2: { 3: public void Configure(IApplicationBuilder app); 4: }對中間件的注冊就是實現(xiàn)在這樣一個Configure方法之中。在演示的實例中,我們調(diào)用了IApplicationBuilder接口的擴展方法Run注冊了一個中間件,它承載的請求處理邏輯很簡單,即使直接響應(yīng)一個“Hello World”字符串。在真實的項目中,我們會根據(jù)具體的應(yīng)用場景在這樣一個方法中利用ApplicationBuilder注冊相應(yīng)的中間件進而構(gòu)建一個適合當前請求處理需求的管道。
1: public class Startup 2: { 3: public void Configure(IApplicationBuilder app) 4: { 5: app.UseExceptionHandler("/Home/Error"); 6: app.UseStaticFiles(); 7: app.UseIdentity(); 8:? 9: app.UseMvc(); 10: } 11: }比如在一個ASP.NET Core MVC應(yīng)用中我們除了按照如上的方式調(diào)用擴展方法UseMvc注冊了支撐MVC框架的中間件(實際上是一個實現(xiàn)路由的中間件)之外,我們還通過調(diào)用其它的擴展方法注冊了相應(yīng)的中間件實現(xiàn)了對靜態(tài)文件的訪問(UseStaticFiles)、錯誤頁面的呈現(xiàn)(UseExceptionHandler)以及基于ASP.NET Identity Framework的認證(UseIdentity)。
?
一、采用管道處理HTTP請求
二、創(chuàng)建一個“迷你版”的管道來模擬真實管道請求處理流程
三、管道如何處理HTTP請求的
四、管道是如何被創(chuàng)建出來的
總結(jié)
以上是生活随笔為你收集整理的ASP.NET Core管道深度剖析(1):采用管道处理HTTP请求的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 完美的17.3寸巨屏游戏本!ROG魔霸6
- 下一篇: 谁说国产车从不召回!制动系统存隐患:奇瑞