參考:
https://www.cnblogs.com/artech/p/inside-asp-net-core-3.html
簡介
.NET Core提供了承載(Hosting)系統,我們可以在它之上寄宿多個長時間運行的服務,ASP.NET Core應用僅僅是該承載系統的一種典型的服務類型而已,任何需要在后台長時間運行的操作都可以定義成標准化的服務並利用該系統來承載。
ASP.NET Core框架目前存在兩個承載(Hosting)系統。ASP.NET Core最初提供了一個以IWebHostBuilder/IWebHost為核心的承載系統,ASP.NET Core 3依然支持這樣的應用承載方式,已過時不介紹;
除了承載Web應用本身,我們還有針對后台服務的承載需求,為此微軟推出了以IHostBuilder/IHost為核心的承載系統。實際上,Web應用本身就是一個長時間運行的后台服務,我們完全可以定義一個承載服務,從而將Web應用承載於這個系統中。如下圖所示,這個用來承載ASP.NET Core應用的承載服務類型為GenericWebHostService,這是一個實現了IHostedService接口的內部類型。
重要接口
IHostedService接口表示承載服務。
IHost接口表示承載服務的宿主。
IHostBuilder接口表示IHost的建造者。
承載服務(IHostedService)
承載服務通過IHostedService接口表示,該接口定義的StartAsync方法和StopAsync方法可以啟動與關閉服務。
一個ASP.NET Core應用本質上是一個需要長時間運行的服務,開啟這個服務是為了啟動一個網絡監聽器(Server)。當監聽到抵達的HTTP請求之后,該監聽器會將請求傳遞給應用提供的管道進行處理。管道完成了對請求處理之后會生成HTTP響應。
這個用來承載ASP.NET Core應用的承載服務類型為GenericWebHostService,這是一個實現了IHostedService接口的內部類型。
當作為宿主的IHost對象被啟動的時候,它會利用依賴注入框架激活每個注冊的IHostedService服務,並通過調用StartAsync方法來啟動它們。當服務承載應用程序關閉的時候,作為服務宿主的IHost對象會被關閉,由它承載的每個IHostedService服務對象的StopAsync方法也隨之被調用。
public interface IHostedService
{
Task StartAsync(CancellationToken cancellationToken);
Task StopAsync(CancellationToken cancellationToken);
}
注冊承載服務有以下兩種方式,他們是等價的:
serviceCollection.AddSingleton<IHostedService, xxxxBackService>();
//由於該方法通過調用TryAddEnumerable擴展方法來注冊服務,所以不用擔心服務重復注冊的問題
serviceCollection.AddHostedService<xxxxBackService>();
依賴注入
服務承載系統無縫整合了依賴注入框架。承載服務被注冊到依賴注入框架中了。既然承載服務實例最終是通過依賴注入框架提供的,那么它自身所依賴的服務當然也可以注冊到依賴注入框架中。
由於承載服務大都需要長時間運行直到應用被關閉,所以針對承載服務的注冊一般采用Singleton生命周期模式。
承載服務的宿主(IHost)
承載服務最終被承載於通過IHost接口表示的宿主上。一般來說,一個服務承載應用在整個生命周期內只會創建一個IHost對象,我們啟動和關閉應用程序本質上就是啟動和關閉作為宿主的IHost對象。
IHost接口的Services屬性返回作為依賴注入容器的IServiceProvider對象,該對象提供了服務承載過程中所需的服務實例,其中就包括需要承載的IHostedService服務。
public interface IHost : IDisposable
{
IServiceProvider Services { get; }
Task StartAsync(CancellationToken cancellationToken = default);
Task StopAsync(CancellationToken cancellationToken = default);
}
Run擴展方法
如果我們調用IHost對象的擴展方法Run,它會在內部調用StartAsync方法,接下來它會持續等待下去直到接收到應用被關閉的通知。當IHost對象對象利用IHostApplicationLifetime服務接收到關於應用關閉的通知后,它會調用自身的StopAsync方法,針對Run方法的調用此時才會返回。啟動IHost對象直到應用關閉這一實現體現在如下這個WaitForShutdownAsync擴展方法上。
public static class HostingAbstractionsHostExtensions
{
public static async Task WaitForShutdownAsync(this IHost host, CancellationToken token = default)
{
var applicationLifetime = host.Services.GetService<IHostApplicationLifetime>();
token.Register(state => ((IHostApplicationLifetime)state).StopApplication(), applicationLifetime);
var waitForStop = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
applicationLifetime.ApplicationStopping.Register(state =>
{
var tcs = (TaskCompletionSource<object>)state;
tcs.TrySetResult(null);
}, waitForStop);
await waitForStop.Task;
await host.StopAsync();
}
}
配置
IHostBuilder接口針對配置系統的設置體現在ConfigureHostConfiguration和ConfigureAppConfiguration方法上。通過前面的實例演示,我們知道ConfigureHostConfiguration方法涉及的配置主要是在服務承載過程中使用的,是針對服務宿主的配置;ConfigureAppConfiguration方法設置的則是供承載的IHostedService服務使用的,是針對應用的配置。不過前者最終會合並到后者之中,我們最終得到的配置實際上是兩者合並的結果。
日志
調用IHostBuilder接口的ConfigureLogging擴展方法注冊了日志框架的核心服務,並利用提供的Action
new HostBuilder()
.ConfigureLogging(builder => builder.AddConsole())
.Build()
.Run();