通過重建Hosting系統理解HTTP請求在ASP.NET Core管道中的處理流程[上]:採用管道處理請求

来源:http://www.cnblogs.com/artech/archive/2016/10/11/rebuild-pipeline-01.html
-Advertisement-
Play Games

ASP.NET Core請求處理管道由一個伺服器和一組中間件構成。如果想非常深刻地認識ASP.NET Core的請求處理管道,我覺得可以分兩個步驟來進行:首先,我們可以在忽略具體細節的前提下搞清楚管道處理HTTP請求的總體流程;在對總體流程有了大致瞭解之後,我們再來補充這些刻意忽略的細節。為了讓讀者... ...


之所以稱ASP.NET Core是一個Web開發平臺,而不是一個單純的開發框架,源於它具有一個極具擴展性的請求處理管道,我們可以通過對這個管道的定製來滿足各種場景下的HTTP處理需求。ASP. NET Core應用的很多特性,比如路由、認證、會話、緩存等,都是通過對管道的定製來實現的。我們甚至可以通過管道定製在ASP.NET Core平臺上創建我們自己的Web框架,實際上MVC和SingalR這兩個重要的Web框架也是採用這樣的方式創建的。 本文已經同步到《ASP.NET Core框架揭秘》之中]

目錄
一、從Hello World說起
二、管道的構成
三、管道的定製

一、從Hello World說起

HTTP協議自身的特性決定了任何一個Web應用的工作方式都是監聽、接收並處理HTTP請求,併在最終對請求予以響應,HTTP請求處理是管道式設計典型的應用場景。具體來說,我們根據具體的HTTP處理請求構建一個管道,接收到的HTTP請求消息想水一樣流入這個管道,組成這個管道的各個環節依次對它作相應的處理。處理的結果同樣轉變成消息逆向流入這個管道進行處理,並最終轉變成回覆給客戶端的HTTP響應。ASP.NET Core的消息處理管道從設計的角度來講是非常簡單的,但是從具體實現的角度則相對複雜並相對難以理解,為了讓讀者朋友們通過本章對此具有深刻的理解,我們從簡單的部分講起。

為了使讀者朋友們能夠以最直觀的感受認識ASP.NET Core的消息處理管道,我們來創建一個最簡單的Hello World程式。這是一個控制台應用,整個程式由如下所示的五行代碼組成。當我們運行這個程式之後,一個名為KestrelServer的伺服器將會啟動並綁定到本機上的5000埠進行請求監聽。針對所有接收到的請求,我們都有會響應一個“Hello World”字元串。

   1: public class Program
   2: {
   3:     public static void Main()
   4:     {
   5:         new WebHostBuilder()
   6:             .UseKestrel()
   7:             .Configure(app => app.Run(async context=> await context.Response.WriteAsync("Hello World")))            
   8:             .Build()
   9:             .Run();
  10:     }
  11: }

這個程式涉及到一個名為WebHost重要的對象, 它可以看成是Web應用的宿主,啟動Web應用本質上就是啟動作為宿主的WebHost對象。WebHostBuilder是WebHost的創建者,我們調用它的Build方法創建相應的WebHost。當我們調用WebHost的擴展方法Run啟動應用的時候,用於監聽、接收、處理和響應HTTP請求的管道隨之被建立。那麼在這個過程中,通過調用Configure方法註冊到WebHostBuilder上的委托對象(委托類型為Action<IApplicationBuilder>)將用於管道的定製。總的來說,ASP.NET Core管道由WebHost在啟動的時候構建,WebHostBuilder則是後者的創建者,下圖揭示了三者之間的關係。

clip_image001 

二、管道的構成

HTTP請求處理流程始於對請求的監聽與接收,終於對請求的響應,這兩項工作均由同一個對象來完成,我們稱之為 “伺服器(Server)” 。儘管ASP.NET Core的請求處理管道可以被自由地訂製,但是該管道必須有一個Server,Server是整個管道的 “龍頭” 。在上面的這個Hello World應用中,在調用WebHostBuilder的Build方法創建一個WebHost之前,我們調用了它的一個擴展方法UseKestrel,這個方法的作用就是為後續構建的管道註冊一個名為KestrelServer的Server。

隨著WebHost的Start方法(當我們調用WebHost的擴展方法Run時,它的Start方法會自動被調用)的調用,定製的管道會被構建出來,管道的伺服器將會綁定到一個預設的埠(比如KestrelServer預設採用5000作為監聽埠)開始監聽請求。HTTP請求一旦抵達,Server會並將其標準並分發給管道後續的節點,我們將管道中位於伺服器之後的節點稱為“中間件(Middleware)”。每個中間件都具有各自獨立的功能,比如我們有專門實現路由功能的中間件,有專門實施用戶認證的中間件。所謂的管道定製體現在根據具體的需求選擇對應的中間件組成最終處理請求的管道。下圖揭示了由一個伺服器和一組中間件構成的請求處理管道。

clip_image002

一個建立在ASP.NET Core之上的應用一般都是根據某個框架開發的,一般來說,開發框架本身就是通過某一個或者多個中間件構建的。以ASP.NET Core MVC這個最著名的開發框架為例,它實際上是藉助於一個叫做 “路由” 的中間件實現了請求地址與Controller/Action之間的映射,併在此基礎實現了激活Controller、執行Action以及呈現View等一系列的功能。所以應用程式可以視為某個中間件的一部分,如果一定要將它獨立出來,整個請求處理管道將呈現出如下圖所示的結構。

clip_image003 

三、管道的定製

在演示的Hello World程式中,我們在調用擴展方法UseKestrel註冊KestrelServer伺服器之後,還調用WebHostBuilder如下一個名為Configure的擴展方法註冊了一個類型為Action<IApplicationBuilder>的委托對象。從請求處理管道的角度來講,註冊這個委托對象的目的在於對構建的管道進行定製,說得更加具體一點,我們利用這個類型為管道註冊需要的中間件。演示實例中註冊的這個委托對象調用ApplicationBuilder的擴展方法Run註冊了一個中間件來為每個請求響應一個 “Hello World” 字元串。

   1: public static IWebHostBuilder Configure(this IWebHostBuilder hostBuilder, Action<IApplicationBuilder> configureApp) 

除了通過調用WebHostBuilder的Configure方法註冊一個Action<IApplicationBuilder>類型的委托,註冊中間定義管道的邏輯更多地還是定義在一個單獨的類型中。由於管道的定製總是在應用啟動(Startup)的時候進行,我們一般稱這個用於定製管道的類型為“啟動類型”,併在大部分情況下會直接命名為Startup。按照約定,通過註冊中間件定製管道的操作會實現在名為Configure的方法中,方法的第一個參數類型必須是IApplicationBuilder介面,後面可定義任意數量和類型的參數,當這個方法被ASP.NET Core框架調用的時候,這些參數會採用依賴註入的方式來提供。啟動類型可以通過調用WebHostBuilder的擴展方法UseStartup<T>進行註冊,如下麵的代碼與前面演示的實例是完全等效的。

   1: public class Program
   2: {
   3:     public static void Main()
   4:     {
   5:         new WebHostBuilder()
   6:             .UseKestrel()
   7:             .UseStartup<Startup>()
   8:             .Build()
   9:             .Run();
  10:     }
  11:     public class Startup
  12:     {
  13:         public void Configure(IApplicationBuilder app)
  14:         {
  15:             app.Run(async context => await context.Response.WriteAsync("Hello World"));
  16:         }
  17:     }
  18: }

在真正的項目開發中,我們會利用ApplicationBuilder註冊相應的中間件進而構建一個適合當前請求處理需求的管道。如下麵的代碼片段所示,我們除了按照如上的方式調用擴展方法UseMvc註冊了支撐MVC框架的中間件(實際上是一個實現路由的中間件)之外,我們還通過調用其它的擴展方法註冊了相應的中間件實現了對靜態文件的訪問(UseStaticFiles)、錯誤頁面的呈現(UseExceptionHandler)以及基於ASP.NET Identity Framework的認證(UseIdentity)。

   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: }

 


通過重建Hosting系統理解HTTP請求在ASP.NET Core管道中的處理流程[上]:採用管道處理請求
通過重建Hosting系統理解HTTP請求在ASP.NET Core管道中的處理流程[中]:管道如何處理請求
通過重建Hosting系統理解HTTP請求在ASP.NET Core管道中的處理流程[下]:管道如何創建


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Areas 是 ASP.NET MVC 用來將相關功能組織成一組單獨命名空間(路由)和文件夾結構(視圖)的功能。使用 Areas 創建層次結構的路由,是通過添加另一個路由參數 `area` 到 `Controller` 和 `action`。 Areas 提供了一種把大型 ASP.NET Core... ...
  • DataBinding is one of the most powerful features in WPF. But because it resolves the bindings at runtime and does not throw exceptions, it's sometimes ...
  • WPF拖動DataGrid滾動條時內容混亂的解決方法 在WPF中,如果DataGrid里使用了模板列,當拖動滾動條時,往往會出現列表內容顯示混亂的情況。解決方法就是在Binding的時候給UpdateSourceTrigger賦值。 後臺代碼如下: ...
  • 1、介紹 vs15是微軟打造的新一代IDE,全新的安裝方式。官網介紹如下(https://blogs.msdn.microsoft.com/visualstudio/2016/10/05/announcing-visual-studio-15-preview-5/): 據微軟描述,Preview 5... ...
  • CUP和.NET SQL版本不同也會存在少許差距,但不會有質變,下麵的測試結果僅供參考 比賽規則 1.統一使用Realse版本的最新 DLL,Realse模式啟用程式 2.為了平衡CPU和資料庫空閑情況,使用車輪戰,每場比賽連續10回合比試 3.多次重啟電腦取平均成績上圖 比賽成員 1.SqlSug ...
  • 目錄 1.簡介... 2 2.適用範圍... 2 3.規範目的... 2 4.代碼組織與風格... 2 4.1 Tab鍵... 2 4.2 縮進... 3 4.3空行... 3 4.4函數長度... 3 4.5行寬... 3 4.6{ “,”} 3 5.文件命名... 3 6.命名... 4 6.1 ...
  • 什麼是ORM? 對象關係映射(英語:Object Relation Mapping,簡稱ORM,或O/RM,或O/R mapping),是一種程式技術,用於實現面向對象編程語言里不同類型系統的數據之間的轉換。從效果上說,它其實是創建了一個可在編程語言里使用的“虛擬對象資料庫”。 一般的ORM包括以下 ...
  • 前兩天朋友問我,有沒有使用過StackExchange.Redis,問我要個封裝類,由於之前都是使用ServiceStack.Redis,由於ServiceStack.Redis v4版本後是收費版的,所以現在也很有公司都在使用StackExchange.Redis而拋棄ServiceStack.R ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...