翻译自 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-5.0
ASP.NET Core 模板创建了一个 .NET Core 通用主机 (Generic Host HostBuilder)。
本话题提供了关于在 ASP.NET Core 中使用 .NET 通用主机。关于在控制台中使用 .NET Generic Host 的信息,查看 .NET Generic Host。
主机定义
主机是指封装了应用程序资源的对象,例如:
- 依赖注入(DI)
- 日志
- 配置
- IHostedService 实现
当一个主机启动的时候,它会调用 IHostedService.StartAsync 在每一个在服务容器中托管服务集合中注册的 IHostedService 的实现。 在 Web 应用程序中,一个 IHostedService 的实现是一个启动 HTTP server implementation 的 web 服务。
包含所有的应用程序相互依赖的资源在一个对象中的主要原因是声明周期管理:控制应用程序启动和优雅的关闭。
设置一个主机
主机一般在 Program 类中通过代码配置,创建,运行。Main 方法:
- 调用 CreateHostBuilder 方法创建和配置一个 builder 对象
- 在 builder 对象上调用 Build 和 Run 方法
ASP.NET Core web 模板生成下列代码创建一个主机:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
下面的代码创建一个 non-HTTP 工作负载,将一个 IHostedService 实现添加到 DI 容器中。
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,不要改变 CreateHostBuiler 方法的名称和签名。Entity Framework Core tools 期望发现一个 CreateHostBuilder 方法,不用运行应用程序就可以配置主机(Host)。更多信息,查看 Design-time DbContext Creation。
默认 builder 设置
- 设置内容根目录(content root)为 GetCurrentDirectory 返回的路径
- 从以下地方加载主机配置:
前缀为 DOTNET_ 的环境变量
命令行参数 - 从以下地方加载应用程序配置:
appsettings.json
appsettings.{Environment}.json
当应用程序运行在 Development 环境时使用 User secrets环境变量
命令行参数 - 添加以下日志(logging)providers:
控制台
调试
EventSource
EventLog (只有运行在 Windows 系统时) - 当环境是 Development 时使能 scope validation 和 dependency validation
- 从前缀为 ASPNETCORE_ 的环境变量中加载主机配置
- 设置 Kestrel 服务器作为 web 服务器,并且使用应用程序 hosting configuration providers 配置它。Kestrel 服务器的默认选项,查看 Configure options for the ASP.NET Core Kestrel web server。
- 添加 Host Filtering middleware。
- 如果 ASPNETCORE_FORWARDEDHEADERS_ENABLED 为 true,添加 Forwarded Headers middleware
- 使能 IIS 集成。关于 IIS 默认选项,查看 Host ASP.NET Core on Windows with IIS
文章中下面的 Settings for all app types 和 Settings for web apps 部分展示了如果覆盖默认 builder 设置。
Framework-provided services
下面的服务会自动注册:
更多关于 framework-provided services 的信息,查看 Dependency injection in ASP.NET Core。
IHostApplicationLifetime
注入 IHostApplicationLifetime (之前叫做 IApplicationLifetime) 服务到任一类中处理 post-startup 和 优雅关闭的任务。接口中的三个属性是用来注册应用程序启动和停止时间处理方法的取消令牌。接口还包括一个 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 的默认实现。
ConsoleLifetime:
- 监听 Ctrl + C / SIGINT or SIGTERM,StopApplication 启动关闭进程
- 疏导扩展,例如 RunAsync 和 WaitForShutdownAsync。
IHostEnvironment
注入服务 IHostEnvironment 到类中获取关于下列设置的信息:
Web 应用程序实现了 IWebHostEnvironment 接口,它继承了 IHostEnvironment 并添加了 WebRootPath。
Host 配置
Host 配置用于 IHostEnvironment 实现的属性。
Host 配置使用 ConfigureAppConfiguration 中的 HostBuilderContext.Configuration。在 ConfigureAppConfiguration 之后,使用应用程序配置替换 HostBuilderContext.Configuration。
为了添加主机配置,调用接口 IHostBuilder 上的 ConfigureHostConfiguration 方法。ConfigureHostConfiguration 可以被多次调用生成累积的结果。主机使用在给定键值最后设置值的选项。
前缀为 DOTNET_ 的环境变量和命令行参数包含在 CreateDefaultBuilder 中。对于 web 应用程序,前缀为 ASPNETCORE_ 的环境变量被添加。当环境变量被读取的时候,前缀会被移除。例如,环境变量 ASPNETCORE_ENVIRONMENT 的值会成为主机配置中 environment 键的值。
下面的示例创建了主机配置:
// using Microsoft.Extensions.Configuration;
Host.CreateDefaultBuilder(args)
.ConfigureHostConfiguration(configHost =>
{
configHost.SetBasePath(Directory.GetCurrentDirectory());
configHost.AddJsonFile("hostsettings.json", optional: true);
configHost.AddEnvironmentVariables(prefix: "PREFIX_");
configHost.AddCommandLine(args);
});
App 配置
App 配置通过调用 IHostBuilder 接口的 ConfigureAppConfiguration 方法创建。ConfigureAppConfiguration 可以多次调用生成累积的结果。App 使用在给定键上最后一个设置值得选项。
创建配置的 ConfigureAppConfiguration 在 HostBuilderContext.Configuration 中,用于后续操作,它作为一个服务从依赖注入 (DI) 中获取。主机配置也会被添加到 App 配置中。
更多信息查看 Configuration in ASP.NET Core。
所有应用程序类型的配置
这部分列出的主机配置会被应用到 HTTP 和 non-HTTP 工作负载中。默认的用来配置这些设置的环境变量可以有一个 DOTNET_ 或者 ASPNETCORE_ 的前缀。更多信息查看 Default builder settings 部分。
ApplicationName
IHostEnvironment.ApplicationName 属性在主机构造方法中通过 host 配置设置。
Key: applicationName
Type: string
Default: 包含应用程序入口点的程序集的名称
Environment variable: <PREFIX_>APPLICATIONNAME
ContentRoot
IHostEnvironment.ContentRootPath 属性决定主机从哪里开始搜索内容文件。如果路径不存在,主机启动失败。
Key: contentRoot
Type: string
Default: 应用程序程序集所在的目录
Environment variable: <PREFIX_>CONTENTROOT
为了设置这个值,使用环境变量或者调用 IHostBuilder 接口的 UseContentRoot 方法:
Host.CreateDefaultBuilder(args)
.UseContentRoot("c:\\content-root")
//...
更多信息查看:
EnvironmentName
IHostEnvironment.EnvironmentName 属性可以被设置为任意值。框架本身定义的值包括 Development,Staging,和 Production。值不区分大小写。
Key: environment
Type: string
Default: Production
Environment variable: <PREFIX_>ENVIRONMENT
使用 IHostBuilder 接口的 UseEnvironment 方法设置这个值:
Host.CreateDefaultBuilder(args)
.UseEnvironment("Development")
//...
ShutdownTimeout
HostOptions.ShutdownTimeout 为 StopAsync 设置超时时间。默认值是 5 秒。在超时时间内,主机会:
- 触发 IHostApplicationLifetime.ApplicationStopping
- 试图停止托管的服务,记录服务停止失败的日志
如果超时时间在所有托管服务停止之前过期了,任何任然活动的服务都会在应用程序关闭的时候停止。即使它们没有完成处理,服务也会停止。如果服务需要更多的时间去停止,请增加超时时间。
Key: shutdownTimeoutSeconds
Type: int
Default: 5 second
Environment variable: <PREFIX_>SHUTDOWNTIMEOUTSECONDS
使用环境变量或者配置 HostOptions 设置这个值。下面的例子设置了超时时间为 20 秒:
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.Configure<HostOptions>(option =>
{
option.ShutdownTimeout = System.TimeSpan.FromSeconds(20);
});
});
禁用配置改变时重新加载应用程序配置
默认的,appsetting.json 和 appsetting.{Environment}.json 文件改变时会被重新加载。在 ASP.NET Core 5.0 或者更新的版本中可以设置 hostBuilder:reloadConfigOnChange 键值为 false 来禁用重新加载的行为。
Key: hostBuilder:reloadCofigOnChange
Type: bool(true or 1)
Default: true
Command-line argument: hostBuilder:reloadConfigOnChange
Environment variable: <PREFIX_>hostBuilder:reloadConfigureOnChange
⚠️ 警告
冒号 (:) 分隔符在所有平台分层键值上的环境变量是不工作的。更多信息查看 Environment variables。
Web 应用程序设置
一些主机设置会应用到 HTTP 工作负载中。默认的,用来配置这些设置的环境变量会有 DOTNET_ 或者 ASPNETCORE_ 前缀。
可以使用 IWebHostBuilder 的扩展方法设置这些配置。例如下面的示例,代码展示了如果调用扩展方法,假设webBuilder 是 IWebHostBuilder 的实例对象:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.CaptureStartupErrors(true);
webBuilder.UseStartup<Startup>();
});
CaptureStartupErrors
当设置为 false 的时候,在启动过程中出现的错误会导致主机退出。当设置为 true 的时候,主机会在启动过程中捕获异常并且试图启动服务器。
Key: captureStartupErrors
Type: bool (true 或者 1)
Default: 默认是 false,除非应用程序使用 Kestrle 运行在 IIS 之后,这时默认值是 true
Environment variable: <PREFIX_>CAPTURESTARTUPERRORS
使用配置或者调用 CaptureStartupErros 设置该值:
webBuilder.CaptureStartupErrors(true);
DetailedErrors
当使能的时候,或者 environment 环境变量是 Development 的时候,应用程序会捕捉详细错误信息。
Key: detailedErrors
Type: bool (true 或者 1)
Default: false
Environment variable: <PREFIXE_>_DETAILEDERRORS
使用配置或者调用 UseSetting 设置该值:
webBuilder.UseSetting(WebHostDefaults.DetailedErrorsKey, "true");
HostingStartupAssemblies
是一个启动时加载的托管的启动程序集的以逗号分隔的字符串。尽管默认配置值是一个空的字符串,托管启动程序集总是包含应用程序的程序集。当托管启动程序集被提供,它们在应用程序启动时创建公共服务的过程中会被添加到应用程序的程序集中加载。
Key: hostingStartupAssemblies
Type: string
Default: Empty string
Environment variable: <PREFIX_>_HOSTINGSTARTUPASSEMBLIES
使用配置或者调用 UseSetting 设置该值:
webBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "assembly1;assembly2");
HostingStartupExcludeAssemblies
启动时排除的托管启动程序集,以逗号分隔的字符串
Key: hostingStartupExcludeAssemblies
Type: string
Default: Empty string
Environment variable: <PREFIX_>_HOSTINGSTARTUPEXCLUDEASSEMBLIES
使用配置或者调用 UseSetting 设置该值:
webBuilder.UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "assembly1;assembly2");
HTTPS_Port
HTTPS 重定向端口。在 enforcing HTTPS 中使用。
Key: https_port
Type: string
Default: A default value isn't set
Environment variable: <PREFIX_>HTTPS_PORT
使用配置或者调用 UseSetting 设置该值:
webBuilder.UseSetting("https_port", "8080");
PreferHostingUrls
标识主机是否应该监听 IWebHostBuilder 配置的 URLs 而不是使用 IServer 的实现配置的 URLs。
Key: preferHostingUrls
Type: bool (true 或者 1)
Default: true
Environment varibale: <PREFIX_>PREFERHOSTINGURLS
使用环境变量或者调用 PreferHostingUrls 设置该值:
webBuilder.PreferHostingUrls(false);
PreventHostingStartup
阻止托管启动程序集的自动加载,包含应用程序程序集配置的托管启动程序集。更多信息查看 Use hosting startup assemblies in ASP.NET Core。
Key: preventHostingStartup
Type:bool (true 或者 1)
Default: false
Environment variable: <PREFIX_>PREVENTHOSTINGSTARTUP
使用环境变量或者调用 UseSetting 设置这个值:
webBuilder.UseSetting(WebHostDefaults.PreventHostingStartupKey, "true");
StartupAssembly
用来查询 Startup 类的程序集。
Key: startupAssembly
Type: string
Default: 应用程序程序集
Environment variable: <PREFIX_>STARTUPASSEMBLY
使用环境变量或者调用 UseStartup 设置这个值。UseStartup 可以接收一个程序集的名称(string)或者一个类型 (TStartup)。如果多个 UseStartup 方法被调用,最后一个优先级最高:
webBuilder.UseStartup("StartupAssemblyName");
webBuilder.UseStartup<Startup>();
URLs
一组逗号分隔的带有端口和协议的 IP 地址或者主机地址,服务器应该在这些地址上监听请求。例如,http://localhost:123。使用 "*" 来表明服务器应该在使用特定端口和协议(例如,http://*:5000)的任意 IP 地址或者主机名称上监听。协议(http:// 或者 https://)必须包含在每一个 URL 中。支持的格式因服务器而异。
Key: urls
Type: string
Default: http://localhost:5000 和 https://localhost:5001
Environment variable: <PREFIX_>URLS
使用环境变量或者调用 UseUrls 设置这个值:
webBuilder.UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002");
Kestrel 有它自己的 enpoint 配置 API。更多信息查看 Configure endpoints for the ASP.NET Core Kestrel web server。
WebRoot
IWebHostEnvironment.WebRootPath 属性决定了应用程序静态资源的相对路径。如果路径不存在,一个 no-op 的文件被使用。
Key: webroot
Type: string
Default: 默认是 wwwroot。路径{content root}/wwwroot 必须存在
Environment variable: <PREFIX_>WEBROOT
使用环境变量或者 IWebHostBuilder 接口的 UseWebRoot 方法设置这个值:
webBuilder.UseWebRoot("public");
更多信息查看:
管理主机生命周期
调用 IHost 的实现方法启动和停止应用程序。这些方法会影响所有注册在服务容器中的 IHostedService 的实现。
Run
Run 运行应用程序,阻塞调用线程直到主机关闭。
RunAsync
RunAsync 运行应用程序,当一个取消令牌或者关闭被触发的时候返回一个完成 Task。
RunConsoleAsync
RunConsoleAsync 使能控制台支持,创建,启动主机,等待 Ctrl + C / SIGINT 或者 SIGTERM 关闭。
Start
Start 以同步方式启动主机
StartAsync
StartAsync 启动主机,当取消令牌或者关闭被触发了,会返回一个完成的 Task。
WaitForStartAsync 在 StartAsync 的开始会被调用,继续运行之前会一直等待它完成。这可以用来延迟启动,直到接收到外部事件的通知。
StopAsync
StopAsync 尝试使用提供的超时时间停止主机
WaitForShutdown
WaitForShutdown 阻塞调用线程直到生命周期 IHostLifttime 的关闭被触发,例如通过 Ctrl + C / SIGINT 或者 SIGTERM。
WaitForShutdownAsync
WaitForShutdownAsync 在通过给定的令牌或者调用 StopAsync 触发关闭的时候回返回一个完成的 Task。
External control
可以通过使用可以在外部调用的方法获取主机声明周期的直接控制权:
public class Program
{
private IHost _host;
public Program()
{
_host = new HostBuilder()
.Build();
}
public async Task StartAsync()
{
_host.StartAsync();
}
public async Task StopAsync()
{
using (_host)
{
await _host.StopAsync(TimeSpan.FromSeconds(5));
}
}
}