.NET Core
应用配置和启动“主机”。 主机负责应用程序启动和生存期管理。 本主题介绍 ASP.NET Core
通用主机 (HostBuilder
),该主机对于托管不处理 HTTP 请求的应用非常有用。 有关 Web 主机 (WebHostBuilder
) 的介绍,请参阅 ASP.NET Core Web 主机
。
通用主机的目标是将 HTTP 管道从 Web 主机 API 中分离出来,从而启用更多的主机方案。 基于通用主机的消息、后台任务和其他非 HTTP 工作负载可从横切功能(如配置、依赖关系注入 [DI] 和日志记录)中受益。
通用主机是 ASP.NET Core 2.1
中的新增功能,不适用于 Web 承载方案。 对于 Web 承载方案,请使用 Web 主机
。 通用主机正处于开发阶段,用于在未来版本中替换 Web 主机,并在 HTTP 和非 HTTP 方案中充当主要的主机 API。
在 Visual Studio Code 中运行示例应用时,请使用外部或集成终端。 请勿在 internalConsole
中运行示例。
在 Visual Studio Code 中设置控制台:
- 打开
.vscode/launch.json
文件。 - 在 .NET Core 启动(控制台)配置中,找到控制台条目。 将值设置为
externalTerminal
或integratedTerminal
。
介绍
通用主机库位于 Microsoft.Extensions.Hosting
命名空间中,由 Microsoft.Extensions.Hosting 包提供。Microsoft.AspNetCore.App 元包
(ASP.NET Core 2.1 或更高版本)中包括 Microsoft.Extensions.Hosting
包。
IHostedService
是执行代码的入口点。 每个 IHostedService
实现都按照 ConfigureServices 中服务注册
的顺序执行。 主机启动时,每个 IHostedService
上都会调用 StartAsync
,主机正常关闭时,以反向注册顺序调用 StopAsync
。
设置主机
IHostBuilder
是供库和应用初始化、生成和运行主机的主要组件:
public static async Task Main(string[] args)
{
var host = new HostBuilder()
.Build();
await host.RunAsync();
}
选项
HostOptions
配置 IHost
的选项。
关闭超时值
ShutdownTimeout
设置 StopAsync
的超时值。 默认值为 5 秒。
Program.Main
中的以下选项配置将默认值为 5 秒的关闭超时值增加至 20 秒:
var host = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
services.Configure<HostOptions>(option =>
{
option.ShutdownTimeout = System.TimeSpan.FromSeconds(20);
});
})
.Build();
默认服务
在主机初始化期间注册以下服务:
环境 (IHostingEnvironment)
HostBuilderContext
- 配置 (
IConfiguration
) IApplicationLifetime(ApplicationLifetime)
IHostLifetime (ConsoleLifetime)
IHost
- 选项 (
AddOptions
) - 日志记录 (
AddLogging
)
主机配置
主机配置的创建方式如下:
- 调用
IHostBuilder
上的扩展方法以设置“内容根
”和“环境
”。 - 从
ConfigureHostConfiguration
中的配置提供程序读取配置。
扩展方法
应用程序键(名称)
IHostingEnvironment.ApplicationName
属性是在主机构造期间通过主机配置设定的。 要显式设置值,请使用 HostDefaults.ApplicationKey
:
密钥:applicationName
类型:string
默认:包含应用入口点的程序集的名称。
设置使用:HostBuilderContext.HostingEnvironment.ApplicationName
环境变量:<PREFIX_>APPLICATIONNAME
(<PREFIX_>
是用户定义的可选前缀)
内容根
此设置确定主机从哪里开始搜索内容文件。
键:contentRoot
类型:string
默认值:默认为应用程序集所在的文件夹。
设置使用:UseContentRoot
环境变量:<PREFIX_>CONTENTROOT
(<PREFIX_>
是用户定义的可选前缀)
如果路径不存在,主机将无法启动。
var host = new HostBuilder()
.UseContentRoot("c:\\<content-root>")
环境
设置应用的环境
。
键:环境
类型:string
默认值:生产
设置使用:UseEnvironment
环境变量:<PREFIX_>ENVIRONMENT
(<PREFIX_>
是用户定义的可选前缀
)
环境可以设置为任何值。 框架定义的值包括 Development``Staging
和 Production
。 值不区分大小写。
var host = new HostBuilder()
.UseEnvironment(EnvironmentName.Development)
ConfigureHostConfiguration
ConfigureHostConfiguration
使用 IConfigurationBuilder
来为主机创建 IConfiguration
。 主机配置用于初始化 IHostingEnvironment
,以供在应用的构建过程中使用。
可多次调用 ConfigureHostConfiguration
,并得到累计结果。 主机使用上一次在一个给定键上设置值的选项。
主机配置自动流向应用配置(ConfigureAppConfiguration
和应用的其余部分)。
默认情况下不包括提供程序。 必须在 ConfigureHostConfiguration
中显式指定应用所需的任何配置提供程序,包括:
- 文件配置(例如,来自
hostsettings.json
文件)。 - 环境变量配置。
- 命令行参数配置。
- 任何其他所需的配置提供程序。
通过使用 SetBasePath
指定应用的基本路径,然后调用其中一个文件配置提供程序
,可以启用主机的文件配置。 示例应用使用 JSON 文件 hostsettings.json,并调用 AddJsonFile
来使用文件的主机配置设置。
要添加主机的环境变量配置
,请在主机生成器上调用 AddEnvironmentVariables
。 AddEnvironmentVariables
接受用户定义的前缀(可选)。 示例应用使用前缀 PREFIX_
。 当系统读取环境变量时,便会删除前缀。 配置示例应用的主机后,PREFIX_ENVIRONMENT
的环境变量值就变成 environment
密钥的主机配置值。
在开发过程中,如果使用 Visual Studio 或通过 dotnet run
运行应用,可能会在 Properties/launchSettings.json 文件中设置环境变量。 若在开发过程中使用 Visual Studio Code,可能会在 .vscode/launch.json 文件中设置环境变量。 有关更多信息,请参见在 ASP.NET Core 中使用多个环境
。
通过调用 AddCommandLine
可添加命令行配置
。 最后添加命令行配置以允许命令行参数替代之前配置提供程序提供的配置。
hostsettings.json:
{
"environment": "Development"
}
可以通过applicationName
和 contentRoot
键提供其他配置。
示例 HostBuilder
配置使用 ConfigureHostConfiguration
:
var host = new HostBuilder()
.ConfigureHostConfiguration(configHost =>
{
configHost.SetBasePath(Directory.GetCurrentDirectory());
configHost.AddJsonFile("hostsettings.json", optional: true);
configHost.AddEnvironmentVariables(prefix: "PREFIX_");
configHost.AddCommandLine(args);
})
ConfigureAppConfiguration
通过在 IHostBuilder
实现上调用 ConfigureAppConfiguration
创建应用配置。 ConfigureAppConfiguration
使用 IConfigurationBuilder
来为应用创建 IConfiguration
。 可多次调用 ConfigureAppConfiguration
,并得到累计结果。 应用使用上一次在一个给定键上设置值的选项。 HostBuilderContext.Configuration
中提供 ConfigureAppConfiguration
创建的配置,以供进行后续操作和在 Services
中使用。
应用配置会自动接收 ConfigureHostConfiguration
提供的主机配置。
示例应用配置使用 ConfigureAppConfiguration
:
var host = new HostBuilder()
.ConfigureAppConfiguration((hostContext, configApp) =>
{
configApp.SetBasePath(Directory.GetCurrentDirectory());
configApp.AddJsonFile("appsettings.json", optional: true);
configApp.AddJsonFile(
$"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json",
optional: true);
configApp.AddEnvironmentVariables(prefix: "PREFIX_");
configApp.AddCommandLine(args);
})
appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
appsettings.Development.json:
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
appsettings.Production.json:
{
"Logging": {
"LogLevel": {
"Default": "Error",
"System": "Information",
"Microsoft": "Information"
}
}
}
要将设置文件移动到输出目录,请在项目文件中将设置文件指定为MSBuild 项目项
。 示例应用移动具有以下 <Content>
项的 JSON 应用设置文件和 hostsettings.json:
<ItemGroup>
<Content Include="**\*.json" Exclude="bin\**\*;obj\**\*" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
ConfigureServices
ConfigureServices
将服务添加到应用的依赖关系
注入容器。 可多次调用 ConfigureServices
,并得到累计结果。
托管服务是一个类,具有实现 IHostedService
接口的后台任务逻辑。 有关更多信息,请参见在 ASP.NET Core 中使用托管服务实现后台任务
。
示例应用使用 AddHostedService
扩展方法向应用添加生存期事件 LifetimeEventsHostedService
和定时后台任务 TimedHostedService
服务:
var host = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
if (hostContext.HostingEnvironment.IsDevelopment())
{
// Development service configuration
}
else
{
// Non-development service configuration
}
services.AddHostedService<LifetimeEventsHostedService>();
services.AddHostedService<TimedHostedService>();
})
ConfigureLogging
ConfigureLogging
添加了一个委托来配置提供的ILoggingBuilder
。 可以利用相加结果多次调用 ConfigureLogging
。
var host = new HostBuilder()
.ConfigureLogging((hostContext, configLogging) =>
{
configLogging.AddConsole();
configLogging.AddDebug();
})
UseConsoleLifetime
UseConsoleLifetime
侦听 Ctrl+C
/SIGINT 或 SIGTERM 并调用 StopApplication
来启动关闭进程。 UseConsoleLifetime
解除阻止 RunAsync
和 WaitForShutdownAsync
等扩展。ConsoleLifetime
预注册为默认生存期实现。 使用注册的最后一个生存期。
var host = new HostBuilder()
.UseConsoleLifetime()
容器配置
为支持插入其他容器中,主机可以接受 IServiceProviderFactory<TContainerBuilder>
。 提供工厂不属于 DI 容器注册,而是用于创建具体 DI 容器的主机内部函数。 UseServiceProviderFactory(IServiceProviderFactory<TContainerBuilder>)
重写用于创建应用的服务提供程序的默认工厂。
ConfigureContainer
方法托管自定义容器配置。 ConfigureContainer
提供在基础主机 API 的基础之上配置容器的强类型体验。 可以利用相加结果多次调用 ConfigureContainer
。
为应用创建服务容器:
namespace GenericHostSample
{
internal class ServiceContainer
{
}
}
提供服务容器工厂:
using System;
using Microsoft.Extensions.DependencyInjection;
namespace GenericHostSample
{
internal class ServiceContainerFactory : IServiceProviderFactory<ServiceContainer>
{
public ServiceContainer CreateBuilder(IServiceCollection services)
{
return new ServiceContainer();
}
public IServiceProvider CreateServiceProvider(ServiceContainer containerBuilder)
{
throw new NotImplementedException();
}
}
}
使用该工厂并为应用配置自定义服务容器:
var host = new HostBuilder()
.UseServiceProviderFactory<ServiceContainer>(new ServiceContainerFactory())
.ConfigureContainer<ServiceContainer>((hostContext, container) =>
{
})
扩展性
在 IHostBuilder
上使用扩展方法实现主机扩展性。 以下示例介绍扩展方法如何使用 在 ASP.NET Core 中使用托管服务实现后台任务
中所示的 TimedHostedService
示例来扩展 IHostBuilder
实现。
var host = new HostBuilder()
.UseHostedService<TimedHostedService>()
.Build();
await host.StartAsync();
应用建立 UseHostedService
扩展方法,以注册在 T
中传递的托管服务:
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
public static class Extensions
{
public static IHostBuilder UseHostedService<T>(this IHostBuilder hostBuilder)
where T : class, IHostedService, IDisposable
{
return hostBuilder.ConfigureServices(services =>
services.AddHostedService<T>());
}
}
管理主机
IHost
实现负责启动和停止服务容器中注册的 IHostedService
实现。
运行
Run
运行应用并阻止调用线程,直到关闭主机:
public class Program
{
public void Main(string[] args)
{
var host = new HostBuilder()
.Build();
host.Run();
}
}
RunAsync
RunAsync
运行应用并返回在触发取消令牌或关闭时完成的 Task
:
public class Program
{
public static async Task Main(string[] args)
{
var host = new HostBuilder()
.Build();
await host.RunAsync();
}
}
RunConsoleAsync
RunConsoleAsync
启用控制台支持、生成和启动主机,以及等待 Ctrl+C
/SIGINT 或 SIGTERM 关闭。
public class Program
{
public static async Task Main(string[] args)
{
var hostBuilder = new HostBuilder();
await hostBuilder.RunConsoleAsync();
}
}
Start
和 StopAsync
Start
同步启动主机。
StopAsync
尝试在提供的超时时间内停止主机。
public class Program
{
public static async Task Main(string[] args)
{
var host = new HostBuilder()
.Build();
using (host)
{
host.Start();
await host.StopAsync(TimeSpan.FromSeconds(5));
}
}
}
StartAsync
和 StopAsync
StartAsync
启动应用。
StopAsync
停止应用。
public class Program
{
public static async Task Main(string[] args)
{
var host = new HostBuilder()
.Build();
using (host)
{
await host.StartAsync();
await host.StopAsync();
}
}
}
WaitForShutdown
WaitForShutdown
通过 IHostLifetime
触发,例如 ConsoleLifetime
(侦听 Ctrl+C
/SIGINT 或 SIGTERM)。 WaitForShutdown
调用 StopAsync
。
public class Program
{
public void Main(string[] args)
{
var host = new HostBuilder()
.Build();
using (host)
{
host.Start();
host.WaitForShutdown();
}
}
}
WaitForShutdownAsync
WaitForShutdownAsync
返回在通过给定的令牌和调用 StopAsync
来触发关闭时完成的 Task
。
public class Program
{
public static async Task Main(string[] args)
{
var host = new HostBuilder()
.Build();
using (host)
{
await host.StartAsync();
await host.WaitForShutdownAsync();
}
}
}
外部控件
使用可从外部调用的方法,能够实现主机的外部控件:
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));
}
}
}
在 StartAsync
开始时调用 WaitForStartAsync
,在继续之前,会一直等待该操作完成。 它可用于延迟启动,直到外部事件发出信号。
IHostingEnvironment
接口
IHostingEnvironment
提供有关应用托管环境的信息。 使用构造函数注入
获取 IHostingEnvironment
以使用其属性和扩展方法:
public class MyClass
{
private readonly IHostingEnvironment _env;
public MyClass(IHostingEnvironment env)
{
_env = env;
}
public void DoSomething()
{
var environmentName = _env.EnvironmentName;
}
}
有关更多信息,请参见在 ASP.NET Core 中使用多个环境
。
IApplicationLifetime
接口
IApplicationLifetime
允许启动后和关闭活动,包括正常关闭请求。 接口上的三个属性是用于注册 Action
方法(用于定义启动和关闭事件)的取消标记。
取消标记 | 触发条件 |
---|---|
ApplicationStarted | 主机已完全启动。 |
ApplicationStopped | 主机正在完成正常关闭。 应处理所有请求。 关闭受到阻止,直到完成此事件。 |
ApplicationStopping | 主机正在执行正常关闭。 仍在处理请求。 关闭受到阻止,直到完成此事件。 |
构造函数将 IApplicationLifetime
服务注入到任何类中。 示例应用将构造函数注入到 LifetimeEventsHostedService
类(一个 IHostedService
实现)中,用于注册事件。
LifetimeEventsHostedService.cs:
internal class LifetimeEventsHostedService : IHostedService
{
private readonly ILogger _logger;
private readonly IApplicationLifetime _appLifetime;
public LifetimeEventsHostedService(
ILogger<LifetimeEventsHostedService> logger, IApplicationLifetime 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
}
}
StopApplication
请求终止应用。 以下类在调用类的 Shutdown
方法时使用 StopApplication
正常关闭应用:
public class MyClass
{
private readonly IApplicationLifetime _appLifetime;
public MyClass(IApplicationLifetime appLifetime)
{
_appLifetime = appLifetime;
}
public void Shutdown()
{
_appLifetime.StopApplication();
}
}