一张图理清ASP.NET Core启动流程
1. 引言
對于ASP.NET Core應(yīng)用程序來說,我們要記住非常重要的一點(diǎn)是:其本質(zhì)上是一個(gè)獨(dú)立的控制臺應(yīng)用,它并不是必需在IIS內(nèi)部托管且并不需要IIS來啟動運(yùn)行(而這正是ASP.NET Core跨平臺的基石)。ASP.NET Core應(yīng)用程序擁有一個(gè)內(nèi)置的Self-Hosted(自托管)的Web Server(Web服務(wù)器),用來處理外部請求。
不管是托管還是自托管,都離不開Host(宿主)。在ASP.NET Core應(yīng)用中通過配置并啟動一個(gè)Host來完成應(yīng)用程序的啟動和其生命周期的管理(如下圖所示)。而Host的主要的職責(zé)就是Web Server的配置和Pilpeline(請求處理管道)的構(gòu)建。
這張圖描述了一個(gè)總體的啟動流程,從上圖中我們知道ASP.NET Core應(yīng)用程序的啟動主要包含三個(gè)步驟:
CreateDefaultBuilder():創(chuàng)建IWebHostBuilder
Build():IWebHostBuilder負(fù)責(zé)創(chuàng)建IWebHost
Run():啟動IWebHost
所以,ASP.NET Core應(yīng)用的啟動本質(zhì)上是啟動作為宿主的WebHost對象。
其主要涉及到兩個(gè)關(guān)鍵對象IWebHostBuilder和IWebHost,它們的內(nèi)部實(shí)現(xiàn)是ASP.NET Core應(yīng)用的核心所在。下面我們就結(jié)合源碼并梳理調(diào)用堆棧來一探究竟!
2. 宿主構(gòu)造器:IWebHostBuilder
在啟動IWebHost宿主之前,我們需要完成對IWebHost的創(chuàng)建和配置。而這一項(xiàng)工作需要借助IWebHostBuilder對象來完成的,ASP.NET Core中提供了默認(rèn)實(shí)現(xiàn)WebHostBuilder。而WebHostBuilder是由WebHost的同名工具類(Microsoft.AspNetCore命名空間下)中的CreateDefaultBuilder方法創(chuàng)建的。
從上圖中我們可以看出CreateDefaultBuilder()方法主要干了六件大事:
UseKestrel:使用Kestrel作為Web server。
UseContentRoot:指定Web host使用的content root(內(nèi)容根目錄),比如Views。默認(rèn)為當(dāng)前應(yīng)用程序根目錄。
ConfigureAppConfiguration:設(shè)置當(dāng)前應(yīng)用程序配置。主要是讀取 appsettinggs.json 配置文件、開發(fā)環(huán)境中配置的UserSecrets、添加環(huán)境變量和命令行參數(shù) 。
ConfigureLogging:讀取配置文件中的Logging節(jié)點(diǎn),配置日志系統(tǒng)。
UseIISIntegration:使用IISIntegration 中間件。
UseDefaultServiceProvider:設(shè)置默認(rèn)的依賴注入容器。
創(chuàng)建完畢WebHostBuilder后,通過調(diào)用UseStartup()來指定啟動類,來為后續(xù)服務(wù)的注冊及中間件的注冊提供入口。
3. 宿主:IWebHost
在ASP.Net Core中定義了IWebHost用來表示W(wǎng)eb應(yīng)用的宿主,并提供了一個(gè)默認(rèn)實(shí)現(xiàn)WebHost。宿主的創(chuàng)建是通過調(diào)用IWebHostBuilder的Build()方法來完成的。那該方法主要做了哪些事情呢,我們來看下面這張【ASP.NET Core啟動流程調(diào)用堆棧】中的黃色邊框部分:
其核心主要在于WebHost的創(chuàng)建,又可以劃分為三個(gè)部分:
構(gòu)建依賴注入容器,初始通用服務(wù)的注冊:BuildCommonService();
實(shí)例化WebHost:var host = new WebHost(...);
初始化WebHost,也就是構(gòu)建由中間件組成的請求處理管道:host.Initialize();
3.1. 注冊初始通用服務(wù)
BuildBuildCommonService方法主要做了兩件事:
查找HostingStartupAttribute特性以應(yīng)用其他程序集中的啟動配置
注冊通用服務(wù)
若配置了啟動程序集,則發(fā)現(xiàn)并以IStartup類型注入到IOC容器中
3.2. 創(chuàng)建IWebHost
public?IWebHost?Build(){ //省略部分代碼var host = new WebHost(applicationServices,hostingServiceProvider,_options,_config,hostingStartupErrors);}host.Initialize(); return host; }3.3. 構(gòu)建請求處理管道
請求管道的構(gòu)建,主要是中間件之間的銜接處理。
而請求處理管道的構(gòu)建,又包含三個(gè)主要部分:
注冊Startup中綁定的服務(wù);
配置IServer;
構(gòu)建管道
請求管道的構(gòu)建主要是借助于IApplicationBuilder,相關(guān)類圖如下:
4. 啟動WebHost
WebHost的啟動主要分為兩步:
再次確認(rèn)請求管道正確創(chuàng)建
啟動Server以監(jiān)聽請求
啟動 HostedService
4.1. 確認(rèn)請求管道的創(chuàng)建
從圖中可以看出,第一步調(diào)用Initialize()方法主要是取保請求管道的正確創(chuàng)建。其內(nèi)部主要是對BuildApplication()方法的調(diào)用,與我們上面所講WebHost的構(gòu)建環(huán)節(jié)具有相同的調(diào)用堆棧。而最終返回的正是由中間件銜接而成的RequestDelegate類型代表的請求管道。
4.2. 啟動Server
我們先來看下類圖:
從類圖中我們可以看出IServer接口主要定義了一個(gè)只讀的特性集合屬性、一個(gè)啟動和停止的方法聲明。在創(chuàng)建宿主構(gòu)造器IWebHostBuilder時(shí)我們通過調(diào)用UseKestrel()方法指定了使用KestrelServer作為默認(rèn)的IServer實(shí)現(xiàn)。其方法申明中接收了一個(gè)IHttpApplication<TContext> application的參數(shù),從命名來看,它代表一個(gè)Http應(yīng)用程序,我們來看下具體的接口定義:
其主要定義了三個(gè)方法,第一個(gè)方法用來創(chuàng)建請求上下文;第二個(gè)方法用來處理請求;第三個(gè)方法用來釋放上下文。而至于請求上下文,是用來攜帶請求和返回響應(yīng)的核心參數(shù),其貫穿與整個(gè)請求處理管道之中。ASP.NET Core中提供了默認(rèn)的實(shí)現(xiàn)HostingApplication,其構(gòu)造函數(shù)接收一個(gè)RequestDelegate _application(也就是鏈接中間件形成的處理管道)用來處理請求。
var httpContextFactory = _applicationServices.GetRequiredService<IHttpContextFactory>();var hostingApp = new HostingApplication(_application, _logger, diagnosticSource, httpContextFactory);4.3. 啟動IHostedService
IHostedService接口用來定義后臺任務(wù),通過實(shí)現(xiàn)該接口并注冊到Ioc容器中,它會隨著ASP.NET Core 程序啟動而啟動,終止而終止。
5. 總結(jié)
結(jié)合源碼,通過對ASP.NET Core運(yùn)行調(diào)用堆棧的梳理,其啟動流程的總體脈絡(luò)一目了然,并且了解到主要的幾個(gè)關(guān)鍵對象:
負(fù)責(zé)創(chuàng)建IWebHost的宿主構(gòu)造器IWebHostBuilder
代表宿主的IWebHost接口
用于構(gòu)建請求管道的IApplicationBuilder
中間件銜接而成的RequestDelegate
代表Web Server的IServer接口
貫穿請求處理管道的請求上下文HttpContext
可以用來注冊后臺服務(wù)的IHostedService接口
這一節(jié)就先從總體上對ASP.NET Core的運(yùn)行原理有個(gè)基本的認(rèn)識,后續(xù)我們再一一講解這幾個(gè)核心對象來加深理解。
原文地址:?http://www.cnblogs.com/sheng-jie/p/7640163.html?
.NET社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關(guān)注
總結(jié)
以上是生活随笔為你收集整理的一张图理清ASP.NET Core启动流程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 随时随地以任意方式编写 .NET 应用程
- 下一篇: 在ASP.NET Core上实施每个租户