什么是主机
主机是封装了应用程序资源的对象,例如:
- 依赖注入
- 日志
- 配置
- IHostedService的实现
当主机启动时,会从DI容器中找到IHostedService接口的所有实现,并调用IHostedService.StartAsync方法。如果是web应用,IHostedService的其中一个实现就是一个web服务,它会启动一个HTTP服务器实现,视情况的不同,HTTP服务器实现可能是Kestrel,IIS HTTP Server或HTTP.sys三者之一,关于此可以查看ASP.NET Core的几种托管方式。
将应用的所有依赖资源包含在一个对象中的主要考虑是:优雅地控制应用的启动和停止。
在ASP.NET Core 3.0之前的版本中,Web Host用来处理HTTP负载。现在,Web Host已经不推荐使用了,它的存在只是为了向前兼容。
启动主机
通常,主机在Program类中配置,构建并运行。在Main方法中:
- 调用CreateHostBuilder方法创建并配置一个builder对象。
- 调用builder对象的Build以及Run方法。
下面是不处理HTTP负载的例子,在DI容器中有一个IHostedService的实现:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});
}
对于有HTTP负载的情况,Main方法还是一样,不过CreateHostBuilder调用了ConfigureWebHostDefaults:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
假如应用要使用Entity Framework Core,不要修改CreateHostBuilder方法的签名,因为Entity Framework Core工具要在不运行应用的情况下配置主机需要找到一个CreateHostBuilder方法。
默认的builder配置
CreateDefaultBuilder方法:
- 将内容根设置为GetCurrentDirectory返回的路径
- 从下列位置加载主机配置:
- 带有 "DOTNET_"前缀的环境变量。
- 命令行参数。
- 从下列位置加载app配置:
- appsettings.json
- appsettings.{Environment}.json
- Secret Manager(如果在开发环境中运行)
- 环境变量
- 命令行参数
- 添加下列的日志支持:
- 控制台
- Debug
- EventSource
- EventLog(仅Windows)
- 在开发环境中启用scope validation和dependency validation
ConfigureWebHostDefaults方法:
- 从带有"ASPNETCORE_"前缀的环境变量中加载主机配置
- 将Kestrel设为Web服务器并使用应用的主机配置提供程序配置
- 添加主机过滤器中间件
- 如果
ASPNETCORE_FORWARDEDHEADERS_ENABLED=true
,添加Forwarded Headers中间件 - 启用IIS集成
框架自带服务
自动注册了以下服务:
- IHostApplicationLifetime
- IHostLifetime
- IHostEnvironment / IWebHostEnvironment
IHostApplicationLifetime
IHostApplicationLifetime以前叫IApplicationLifetime,将该服务注入到任何类里,可以用来处理应用程序生命周期事件(启动和停止)。 该接口还包括一个StopApplication 方法。
下面的例子是一个IHostedService接口的实现,并注册了IHostApplicationLifetime事件:
internal class LifetimeEventsHostedService : IHostedService
{
private readonly ILogger _logger;
private readonly IHostApplicationLifetime _appLifetime;
public LifetimeEventsHostedService(
ILogger<LifetimeEventsHostedService> logger,
IHostApplicationLifetime appLifetime)
{
_logger = logger;
_appLifetime = appLifetime;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_appLifetime.ApplicationStarted.Register(OnStarted);
_appLifetime.ApplicationStopping.Register(OnStopping);
_appLifetime.ApplicationStopped.Register(OnStopped);
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
private void OnStarted()
{
_logger.LogInformation("OnStarted has been called.");
// Perform post-startup activities here
}
private void OnStopping()
{
_logger.LogInformation("OnStopping has been called.");
// Perform on-stopping activities here
}
private void OnStopped()
{
_logger.LogInformation("OnStopped has been called.");
// Perform post-stopped activities here
}
}
IHostLifetime
IHostLifetime的实现控制什么时候启动和停止主机,使用最后注册的那个实现,这意味着可以重写默认实现。
Microsoft.Extensions.Hosting.Internal.ConsoleLifetime
是IHostLifetime的默认实现,它:
- 监听Ctrl+C/SIGINT或SIGTERM并调用StopApplication启动关闭进程
- 非阻塞的扩展方法,例如RunAsync以及WaitForShutdownAsync
IHostEnvironment
注入该服务可以获取如下信息:
- 应用名称
- 环境名称
- 内容根路径
Web应用实现了IWebHostEnvironment接口,该接口继承了IHostEnvironmentbiang,并新增了一个WebRootPath。