Hosting in .NET Core
在.NET Core中,Host負責應用程序的啟動和生命周期管理。除此之外,在Host中還可以設置日志(Logging)、配置(Configuration)和依賴關系注入(Dependency Injection)等。Host將一個常規的控制臺應用程序(Console Application)變成了一個可以長時間運行的服務(Long-running Service)。
Hosting History
在.NET Core中,有以下2個Host:
.NET Generic Host(簡稱 Generic Host)
ASP.NET Core Web Host(簡稱 Web Host)
要了解它們之間的區別與聯系,我們需要從.NET Core的發展歷程中尋找答案。
微軟在2016年6月發布了.NET Core 1.0。.NET Core是一個開放的、支持跨平臺的框架,它與.NET Framework有著顯著的不同。在這之后微軟又陸續發布了.NET Core 1.1、.NET Core 2.0、.NET Core 2.1、.NET Core 2.2、.NET Core 3.0和.NET Core 3.1。
Web Host在.NET Core 1.0中被引入,它被用于配置并啟動KestrelWeb服務器,在指定的端口上監聽HTTP請求。Web Host正如它的名稱所言,只用于Host ASP.NET Core Web Application。
Generic Host在.NET Core 2.1中被引入,但它只被用于non-HTTP的場景,例如hosted services/worker services。此時你仍需要使用Web Host來Host ASP.NET Core Web Application。這帶來了一定的混淆和麻煩,很多相近的類被引入。
IWebHost 與 IHost,IWebHostBuilder與IHostBuilder
| IWebHost | Microsoft.AspNetCore.Hosting | WebHost | https://github.com/dotnet/aspnetcore | src/Hosting/Hosting/src/Internal/WebHost.cs |
| IHost | Microsoft.Extensions.Hosting | Host | https://github.com/dotnet/runtime | src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs |
| IWebHostBuilder | Microsoft.AspNetCore.Hosting | WebHostBuilder | https://github.com/dotnet/aspnetcore | src/Hosting/Hosting/src/WebHostBuilder.cs |
| IHostBuilder | Microsoft.Extensions.Hosting | HostBuilder | https://github.com/dotnet/runtime | src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs |
還有與這些接口相關的靜態輔助類:
| WebHost | Microsoft.AspNetCore | https://github.com/dotnet/aspnetcore | src/DefaultBuilder/src/WebHost.cs |
| Host | Microsoft.Extensions.Hosting | https://github.com/dotnet/runtime | src/libraries/Microsoft.Extensions.Hosting/src/Host.cs |
我們在Program.cs文件中一般都是用這兩個靜態輔助類來創建IWebHost或IHost的具體實例,進而啟動應用程序。
IHostingEnvironment?vs?IHostEnvironment?vs?IWebHostEnvironment
這幾個接口是不是傻傻分不清?這其實充分說明了微軟在主導.NET Core的開發過程中存在著管理和命名的混亂。這也難免,畢竟這么大的項目,而且代碼庫也是各管各的。
首先IHostingEnvironment存在于2個不同的命名空間中,雖然接口內容大致相同,但卻是互不兼容的——它們之間沒有繼承關系。
| IHostingEnvironment | Microsoft.AspNetCore.Hosting | https://github.com/dotnet/aspnetcore | src/Hosting/Abstractions/src/IHostingEnvironment.cs |
| IHostingEnvironment | Microsoft.Extensions.Hosting | https://github.com/dotnet/runtime | src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/IHostingEnvironment.cs |
從.NET Core 3.0起,這兩個接口都被標記為obsolete,取而代之的分別是IWebHostEnvironment 與 IHostEnvironment。它們依然存在于不同的命名空間中,但它們之間有了繼承關系。
| IWebHostEnvironment | Microsoft.AspNetCore.Hosting | https://github.com/dotnet/aspnetcore | src/Hosting/Abstractions/src/IWebHostEnvironment.cs |
| IHostEnvironment | Microsoft.Extensions.Hosting | https://github.com/dotnet/runtime | src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/IHostEnvironment.cs |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | namespace Microsoft.AspNetCore.Hosting {public interface IWebHostEnvironment : IHostEnvironment{string WebRootPath { get; set; }IFileProvider WebRootFileProvider { get; set; }} }namespace Microsoft.Extensions.Hosting {public interface IHostEnvironment{string EnvironmentName { get; set; }string ApplicationName { get; set; }string ContentRootPath { get; set; }IFileProvider ContentRootFileProvider { get; set; }} } |
這樣的設計就很合理,也減少了重復。它們各自的默認實現也基本相同。
| HostingEnvironment | Microsoft.AspNetCore.Hosting | https://github.com/dotnet/aspnetcore | src/Hosting/Hosting/src/Internal/HostingEnvironment.cs |
| HostingEnvironment | Microsoft.Extensions.Hosting.Internal | https://github.com/dotnet | src/libraries/Microsoft.Extensions.Hosting/src/Internal/HostingEnvironment.cs |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | namespace Microsoft.AspNetCore.Hosting {internal class HostingEnvironment : IHostingEnvironment, Extensions.Hosting.IHostingEnvironment,IWebHostEnvironment{public string EnvironmentName { get; set; } = Extensions.Hosting.Environments.Production;public string ApplicationName { get; set; }public string WebRootPath { get; set; }public IFileProvider WebRootFileProvider { get; set; }public string ContentRootPath { get; set; }public IFileProvider ContentRootFileProvider { get; set; }} }namespace Microsoft.Extensions.Hosting.Internal {public class HostingEnvironment : IHostingEnvironment, IHostEnvironment{public string EnvironmentName { get; set; }public string ApplicationName { get; set; }public string ContentRootPath { get; set; }public IFileProvider ContentRootFileProvider { get; set; }} } |
Generic Host 取代 Web Host
時間來到了.NET Core 3.0發布。微軟重構了Generic Host,使之成為一個真正的通用的Host——可同時運行Worker Services和Web Applications。這大大簡化了Host的模型及相關的類,開發者理解和使用起來更加容易了。
圖片來自PluralSight課程
小結
盡可能地使用IHostEnvironment
官方不建議在.NET Core 3.0及以上的版本中使用Web Host
對于ASP.NET Core Web Application來說,Kestrel Web Server被包裝在GenericWebHostService中被Generic Host初始化并啟動
微軟于2020年11月發布了.NET 5。.NET 5是.NET Core的下一個版本,被描述為.NET統一之旅中的第一個版本,它是為了使更多的開發人員能夠將.NET框架代碼和應用遷移到.NET 5。該平臺將來自.NET Framework、.NET Core和Mono的代碼組合在一起,為所有現代.NET應用提供一個單一的平臺。本文所討論的.NET Generic Host同樣適用于.NET 5。
CreateDefaultBuilder與ConfigureWebHostDefaults
一般情況下,我們使用靜態輔助類Host中的CreateDefaultBuilder方法來創建IHostBuilder的實例。對于ASP.NET Core Web Application,我們還會調用ConfigureWebHostDefaults方法。我們需要了解這兩個方法到底做了哪些默認的設置,以便減少不必要、多余的設置。
CreateDefaultBuilder 方法
將內容根目錄設置為由 GetCurrentDirectory 返回的路徑
通過以下項加載主機配置:
前綴為 DOTNET_ 的環境變量
命令行參數
通過以下項加載應用配置:
appsettings.json
appsettings.{Environment}.json
在 Development 環境中運行時的用戶機密配置信息(secrets.json)
環境變量
命令行參數
添加以下日志提供程序:
控制臺
調試
EventSource
EventLog(僅當在 Windows 上運行時)
在 Development 環境中,啟用范圍驗證和依賴關系驗證
圖片來自PluralSight課程
ConfigureWebHostDefaults 方法
從前綴為 ASPNETCORE_ 的環境變量加載主機配置。
使用應用的托管配置提供程序將 Kestrel 服務器設置為 web 服務器并對其進行配置。
如果 ASPNETCORE_FORWARDEDHEADERS_ENABLED 等于 true,則添加轉接頭中間件(ForwardedHeadersStartupFilter)。
添加 IIS 集成。
推薦閱讀源代碼了解更多的實現細節
CreateDefaultBuilder
ConfigureDefaults
ConfigureWebHostDefaults
GenericWebHostBuilder
ConfigureWebDefaults
ConfigureWebHost
Generic Host 的啟動與停止
啟動
Generic Host 的啟動步驟如下:
在Program.cs文件中,通過CreateDefaultBuilder構建一個IHost的實例
調用IHost上的靜態擴展方法Run或RunAsync,這會間接調用到IHost的StartAsync方法
IHost的StartAsync方法則會遍歷所有注冊的IHostedService,調用它的StartAsync方法
IHost上的靜態擴展方法[Run或RunAsync]會調用另一個擴展方法——WaitForShutdownAsync,等待程序結束的信號
圖片來自PluralSight課程
.NET Core 應用程序運行后會創建名為.NET Host(dotnet.exe)的后臺進程。
停止
Generic Host 的停止步驟如下:
用戶使用Ctrl + C或者應用程序使用代碼來發出程序結束的信號
IHost的StopAsync方法在WaitForShutdownAsync中被調用
所有注冊的IHostedService的StopAsync方法被調用
應用程序退出
圖片來自PluralSight課程
需要指出的是,IHostedService的注冊順序是非常重要的,啟動的時候是按注冊順序,停止的時候則是倒序。
其它的Host
在Windows操作系統中,你還會看到很多其它的Host。
Console Window Host(conhost.exe)
Console Window Host, 即命令行程序的宿主進程。典型的命令行程序有cmd.exe、nslookup.exe等。Console Window Host負責繪制命令行程序的圖形化窗口,管理輸入緩沖區和屏幕緩沖區。
Service Host(svchost.exe)
Service Host是一個共有的宿主進程的名稱,它用來運行DLL文件中的服務,特別是很多系統服務。為了使這些服務之間保持隔離,減少相互影響導致的程序錯誤,系統會運行很多個Service Host的進程實例。你可以使用Process Explorer這個工具,通過Command Line列來區分它們。
DLL Host(dllhost.exe)
DLL Host程序又稱為COM Surrogate,它是COM組件的宿主進程。COM(Component Object Model,組件對象模型)是微軟于1993年提出的一種軟件開發技術,它定義了組件對象進行交互的二進制接口標準。COM組件大多以動態鏈接庫(DLL)的形式發布,DLL Host(dllhost.exe)則正是加載這些COM組件的宿主程序。與Service Host類似,系統會運行很多個DLL Host的進程實例。你可以使用Process Explorer這個工具,通過Command Line列來區分它們。
參考資料
ASP.NET Core Web Host
.NET Generic Host in ASP.NET Core
Building ASP.NET Core Hosted Services and .NET Core Worker Services
Introducing .NET Core
Announcing .NET Core 1.0
Announcing .NET 5.0
Understanding .NET Generic Host Model
Generic Host Builder in ASP .NET Core 3.1
Changes to Service Host grouping in Windows 10
總結
以上是生活随笔為你收集整理的Hosting in .NET Core的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 常用加解密工具集合|视频图片加解密方案
- 下一篇: ASP.NET Core 单元测试:如何