ASP.NET Core 應用配置和啟動主機。 主機負責應用程序啟動和生存期管理。
本文介紹 ASP.NET Core 泛型主機 (HostBuilder),該主機用于無法處理 HTTP 請求的應用。
泛型主機的用途是將 HTTP 管道從 Web 主機 API 中分離出來,從而啟用更多的主機方案。 基于泛型主機的消息、后臺任務和其他非 HTTP 工作負載可從橫切功能(如配置、依賴關系注入 [DI] 和日志記錄)中受益。
泛型主機是 ASP.NET Core 2.1 中的新增功能,不適用于 Web 承載方案。 對于 Web 承載方案,請使用 Web 主機。 泛型主機將在未來版本中替換 Web 主機,并在 HTTP 和非 HTTP 方案中充當主要的主機 API。
在 Visual Studio Code 中運行示例應用時,請使用外部或集成終端。 請勿在 internalConsole 中運行示例。
在 Visual Studio Code 中設置控制臺:
通用主機庫位于 Microsoft.Extensions.Hosting 命名空間中,由 Microsoft.Extensions.Hosting 包提供。 Microsoft.AspNetCore.App 元包(ASP.NET Core 2.1 或更高版本)中包括 Microsoft.Extensions.Hosting 包。
IHostedService 是執(zhí)行代碼的入口點。 每個 IHostedService 實現(xiàn)都按照 ConfigureServices 中服務注冊的順序執(zhí)行。 主機啟動時,每個 IHostedService 上都會調(diào)用 StartAsync,主機正常關閉時,以反向注冊順序調(diào)用 StopAsync。
IHostBuilder 是供庫和應用初始化、生成和運行主機的主要組件:
C#
public static async Task Main(string[] args)
{
var host = new HostBuilder()
.Build();
await host.RunAsync();
}
HostOptions 配置 IHost 的選項。
ShutdownTimeout 設置 StopAsync 的超時值。 默認值為 5 秒。
Program.Main 中的以下選項配置將默認值為 5 秒的關閉超時值增加至 20 秒:
C#
var host = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
services.Configure<HostOptions>(option =>
{
option.ShutdownTimeout = System.TimeSpan.FromSeconds(20);
});
})
.Build();
在主機初始化期間注冊以下服務:
主機配置的創(chuàng)建方式如下:
IHostingEnvironment.ApplicationName 屬性是在主機構造期間通過主機配置設定的。 要顯式設置值,請使用 HostDefaults.ApplicationKey:
密鑰:applicationName類型:string默認值:包含應用入口點的程序集的名稱。設置使用:HostBuilderContext.HostingEnvironment.ApplicationName環(huán)境變量:<PREFIX_>APPLICATIONNAME(<PREFIX_> 是用戶定義的可選前綴)
此設置確定主機從哪里開始搜索內(nèi)容文件。
鍵:contentRoot類型:string默認值:默認為應用程序集所在的文件夾。設置使用:UseContentRoot環(huán)境變量:<PREFIX_>CONTENTROOT(<PREFIX_> 是用戶定義的可選前綴)
如果路徑不存在,主機將無法啟動。
C#
var host = new HostBuilder()
.UseContentRoot("c:\\<content-root>")
設置應用的環(huán)境。
鍵:環(huán)境類型:string默認值:生產(chǎn)設置使用:UseEnvironment環(huán)境變量:<PREFIX_>ENVIRONMENT(<PREFIX_> 是用戶定義的可選前綴)
環(huán)境可以設置為任何值。 框架定義的值包括 Development``Staging 和 Production。 值不區(qū)分大小寫。
C#
var host = new HostBuilder()
.UseEnvironment(EnvironmentName.Development)
ConfigureHostConfiguration 使用 IConfigurationBuilder 來為主機創(chuàng)建 IConfiguration。 主機配置用于初始化 IHostingEnvironment,以供在應用的構建過程中使用。
可多次調(diào)用 ConfigureHostConfiguration,并得到累計結果。 主機使用上一次在一個給定鍵上設置值的選項。
主機配置自動流向應用配置(ConfigureAppConfiguration 和應用的其余部分)。
默認情況下不包括提供程序。 必須在 ConfigureHostConfiguration 中顯式指定應用所需的任何配置提供程序,包括:
通過使用 SetBasePath 指定應用的基本路徑,然后調(diào)用其中一個文件配置提供程序,可以啟用主機的文件配置。 示例應用使用 JSON 文件 hostsettings.json,并調(diào)用 AddJsonFile 來使用文件的主機配置設置。
要添加主機的環(huán)境變量配置,請在主機生成器上調(diào)用 AddEnvironmentVariables。 AddEnvironmentVariables 接受用戶定義的前綴(可選)。 示例應用使用前綴 PREFIX_。 當系統(tǒng)讀取環(huán)境變量時,便會刪除前綴。 配置示例應用的主機后,PREFIX_ENVIRONMENT 的環(huán)境變量值就變成 environment 密鑰的主機配置值。
在開發(fā)過程中,如果使用 Visual Studio 或通過 dotnet run 運行應用,可能會在 Properties/launchSettings.json 文件中設置環(huán)境變量。 若在開發(fā)過程中使用 Visual Studio Code,可能會在 .vscode/launch.json 文件中設置環(huán)境變量。 有關更多信息,請參見在 ASP.NET Core 中使用多個環(huán)境。
通過調(diào)用 AddCommandLine 可添加命令行配置。 最后添加命令行配置以允許命令行參數(shù)替代之前配置提供程序提供的配置。
hostsettings.json:
C#
{
"environment": "Development"
}
可以通過 applicationName 和 contentRoot 鍵提供其他配置。
示例 HostBuilder 配置使用 ConfigureHostConfiguration:
C#
var host = new HostBuilder()
.ConfigureHostConfiguration(configHost =>
{
configHost.SetBasePath(Directory.GetCurrentDirectory());
configHost.AddJsonFile("hostsettings.json", optional: true);
configHost.AddEnvironmentVariables(prefix: "PREFIX_");
configHost.AddCommandLine(args);
})
通過在 IHostBuilder 實現(xiàn)上調(diào)用 ConfigureAppConfiguration 創(chuàng)建應用配置。ConfigureAppConfiguration 使用 IConfigurationBuilder 來為應用創(chuàng)建 IConfiguration。 可多次調(diào)用 ConfigureAppConfiguration,并得到累計結果。 應用使用上一次在一個給定鍵上設置值的選項。HostBuilderContext.Configuration 中提供 ConfigureAppConfiguration 創(chuàng)建的配置,以供進行后續(xù)操作和在 Services 中使用。
應用配置會自動接收 ConfigureHostConfiguration 提供的主機配置。
示例應用配置使用 ConfigureAppConfiguration:
C#
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:
C#
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
appsettings.Development.json:
C#
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
appsettings.Production.json:
C#
{
"Logging": {
"LogLevel": {
"Default": "Error",
"System": "Information",
"Microsoft": "Information"
}
}
}
要將設置文件移動到輸出目錄,請在項目文件中將設置文件指定為 MSBuild 項目項。 示例應用移動具有以下 <Content> 項的 JSON 應用設置文件和 hostsettings.json:
XML
<ItemGroup>
<Content Include="**\*.json" Exclude="bin\**\*;obj\**\*"
CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
ConfigureServices 將服務添加到應用的依賴關系注入容器。 可多次調(diào)用 ConfigureServices,并得到累計結果。
托管服務是一個類,具有實現(xiàn) IHostedService 接口的后臺任務邏輯。 有關更多信息,請參見在 ASP.NET Core 中使用托管服務實現(xiàn)后臺任務。
示例應用使用 AddHostedService 擴展方法向應用添加生存期事件 LifetimeEventsHostedService 和定時后臺任務 TimedHostedService 服務:
C#
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 添加了一個委托來配置提供的 ILoggingBuilder。 可以利用相加結果多次調(diào)用 ConfigureLogging。
C#
var host = new HostBuilder()
.ConfigureLogging((hostContext, configLogging) =>
{
configLogging.AddConsole();
configLogging.AddDebug();
})
UseConsoleLifetime 偵聽 Ctrl+C/SIGINT 或 SIGTERM 并調(diào)用 StopApplication 來啟動關閉進程。UseConsoleLifetime 解除阻止 RunAsync 和 WaitForShutdownAsync 等擴展。 ConsoleLifetime 預注冊為默認生存期實現(xiàn)。 使用注冊的最后一個生存期。
C#
var host = new HostBuilder()
.UseConsoleLifetime()
為支持插入其他容器中,主機可以接受 IServiceProviderFactory<TContainerBuilder>。 提供工廠不屬于 DI 容器注冊,而是用于創(chuàng)建具體 DI 容器的主機內(nèi)部函數(shù)。UseServiceProviderFactory(IServiceProviderFactory<TContainerBuilder>) 重寫用于創(chuàng)建應用的服務提供程序的默認工廠。
ConfigureContainer 方法托管自定義容器配置。 ConfigureContainer 提供在基礎主機 API 的基礎之上配置容器的強類型體驗。 可以利用相加結果多次調(diào)用 ConfigureContainer。
為應用創(chuàng)建服務容器:
C#
namespace GenericHostSample
{
internal class ServiceContainer
{
}
}
提供服務容器工廠:
C#
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();
}
}
}
使用該工廠并為應用配置自定義服務容器:
C#
var host = new HostBuilder()
.UseServiceProviderFactory<ServiceContainer>(new ServiceContainerFactory())
.ConfigureContainer<ServiceContainer>((hostContext, container) =>
{
})
在 IHostBuilder 上使用擴展方法實現(xiàn)主機擴展性。 以下示例介紹擴展方法如何使用 在 ASP.NET Core 中使用托管服務實現(xiàn)后臺任務 中所示的 TimedHostedService 示例來擴展 IHostBuilder 實現(xiàn)。
C#
var host = new HostBuilder()
.UseHostedService<TimedHostedService>()
.Build();
await host.StartAsync();
應用建立 UseHostedService 擴展方法,以注冊在 T 中傳遞的托管服務:
C#
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 實現(xiàn)負責啟動和停止服務容器中注冊的 IHostedService 實現(xiàn)。
Run 運行應用并阻止調(diào)用線程,直到關閉主機:
C#
public class Program
{
public void Main(string[] args)
{
var host = new HostBuilder()
.Build();
host.Run();
}
}
RunAsync 運行應用并返回在觸發(fā)取消令牌或關閉時完成的 Task:
C#
public class Program
{
public static async Task Main(string[] args)
{
var host = new HostBuilder()
.Build();
await host.RunAsync();
}
}
RunConsoleAsync 啟用控制臺支持、生成和啟動主機,以及等待 Ctrl+C/SIGINT 或 SIGTERM 關閉。
C#
public class Program
{
public static async Task Main(string[] args)
{
var hostBuilder = new HostBuilder();
await hostBuilder.RunConsoleAsync();
}
}
Start 同步啟動主機。
StopAsync 嘗試在提供的超時時間內(nèi)停止主機。
C#
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 停止應用。
C#
public class Program
{
public static async Task Main(string[] args)
{
var host = new HostBuilder()
.Build();
using (host)
{
await host.StartAsync();
await host.StopAsync();
}
}
}
WaitForShutdown 通過 IHostLifetime 觸發(fā),例如 ConsoleLifetime(偵聽 Ctrl+C/SIGINT 或 SIGTERM)。 WaitForShutdown 調(diào)用 StopAsync。
C#
public class Program
{
public void Main(string[] args)
{
var host = new HostBuilder()
.Build();
using (host)
{
host.Start();
host.WaitForShutdown();
}
}
}
WaitForShutdownAsync 返回在通過給定的令牌和調(diào)用 StopAsync 來觸發(fā)關閉時完成的 Task。
C#
public class Program
{
public static async Task Main(string[] args)
{
var host = new HostBuilder()
.Build();
using (host)
{
await host.StartAsync();
await host.WaitForShutdownAsync();
}
}
}
使用可從外部調(diào)用的方法,能夠實現(xiàn)主機的外部控件:
C#
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 開始時調(diào)用 WaitForStartAsync,在繼續(xù)之前,會一直等待該操作完成。 它可用于延遲啟動,直到外部事件發(fā)出信號。
IHostingEnvironment 提供有關應用托管環(huán)境的信息。 使用構造函數(shù)注入獲取 IHostingEnvironment以使用其屬性和擴展方法:
C#
public class MyClass
{
private readonly IHostingEnvironment _env;
public MyClass(IHostingEnvironment env)
{
_env = env;
}
public void DoSomething()
{
var environmentName = _env.EnvironmentName;
}
}
有關更多信息,請參見在 ASP.NET Core 中使用多個環(huán)境。
IApplicationLifetime 允許啟動后和關閉活動,包括正常關閉請求。 接口上的三個屬性是用于注冊 Action 方法(用于定義啟動和關閉事件)的取消標記。
取消標記 | 觸發(fā)條件 |
---|---|
ApplicationStarted | 主機已完全啟動。 |
ApplicationStopped | 主機正在完成正常關閉。 應處理所有請求。 關閉受到阻止,直到完成此事件。 |
ApplicationStopping | 主機正在執(zhí)行正常關閉。 仍在處理請求。 關閉受到阻止,直到完成此事件。 |
構造函數(shù)將 IApplicationLifetime 服務注入到任何類中。 示例應用將構造函數(shù)注入到 LifetimeEventsHostedService 類(一個 IHostedService 實現(xiàn))中,用于注冊事件。
LifetimeEventsHostedService.cs:
C#
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 請求終止應用。 以下類在調(diào)用類的 Shutdown 方法時使用 StopApplication 正常關閉應用:
C#
public class MyClass
{
private readonly IApplicationLifetime _appLifetime;
public MyClass(IApplicationLifetime appLifetime)
{
_appLifetime = appLifetime;
}
public void Shutdown()
{
_appLifetime.StopApplication();
}
}
更多建議: