(16)ASP.NET Core 通用主機(HostBuilder)
1.前言
ASP.NET Core應用程式可以配置和啟動主機(Host)。主機負責應用程式啟動和生命周期管理。通用主機用于無法處理HTTP請求的應用程式。通用主機的用途是将HTTP管道從Web主機API中分離出來,進而啟用更多的主機方案。 基于通用主機的消息、背景任務和其他非HTTP工作負載可從橫切功能(如配置、依賴關系注入[DI]和日志記錄)中受益。通用主機是ASP.NET Core 2.1中的新增功能,不适用于Web承載方案。對于Web承載方案,請使用Web主機。通用主機将在未來版本中替換Web主機,并在HTTP和非HTTP方案中充當主要的主機API。
2.介紹
IHostedService是執行代碼的入口點。每個IHostedService實作都按照ConfigureServices中服務注冊的順序執行。主機啟動時,每個IHostedService上都會調用StartAsync,主機正常關閉時,以反向注冊順序調用StopAsync。
3.設定主機
IHostBuilder是供庫和應用程式初始化、生成和運作主機的主要元件:
public static async Task Main(string[] args)
{
var host = new HostBuilder().Build();
await host.RunAsync();
}
4.選項
HostOptions配置IHost的選項。
4.1關閉逾時值
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();
5.預設服務
在主機初始化期間注冊以下服務:
●環境 (IHostingEnvironment)
●HostBuilderContext
●配置 (IConfiguration)
●IApplicationLifetime (ApplicationLifetime)
●IHostLifetime (ConsoleLifetime)
●IHost
●選項 (AddOptions)
●日志記錄 (AddLogging)
6.主機配置
主機配置的建立方式如下:
●調用IHostBuilder上的擴充方法以設定“内容根”和“環境”。
●從ConfigureHostConfiguration中的配置提供應用程式讀取配置。
●應用程式鍵(名稱)、内容根、環境配置方式我就不多說了,跟上一篇Web主機配置是一樣的。
6.1ConfigureHostConfiguration
ConfigureHostConfiguration使用IConfigurationBuilder來為主機建立IConfiguration。主機配置用于初始化IHostingEnvironment,以供在應用程式的建構過程中使用。可多次調用ConfigureHostConfiguration,并得到累計結果。必須在ConfigureHostConfiguration中顯式指定應用程式所需的任何配置提供自身,包括:
●檔案配置(例如,來自hostsettings.json檔案)。
●環境變量配置。
●指令行參數配置。
●任何其他所需的配置提供程式。
通過使用SetBasePath指定應用程式的基本路徑,然後調用其中一個檔案配置提供應用程式,可以啟用主機的檔案配置。示例應用使用JSON檔案hostsettings.json,并調用AddJsonFile來使用檔案的主機配置設定。要添加主機的環境變量配置,請在主機生成器上調用 AddEnvironmentVariables。AddEnvironmentVariables接受使用者定義的字首(可選)。示例應用程式使用字首PREFIX_。當系統讀取環境變量時,便會删除字首。配置示例應用程式的主機後,PREFIX_ENVIRONMENT的環境變量值就變成environment密鑰的主機配置值。示例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);
})
6.2ConfigureAppConfiguration
通過在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);
})
6.3ConfigureServices
ConfigureServices将服務添加到應用程式的依賴關系注入容器。可多次調用ConfigureServices,并得到累計結果。托管服務是一個類,具有實作IHostedService接口的背景任務邏輯。示例應用程式使用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>();
})
6.4ConfigureLogging
ConfigureLogging添加了一個委托來配置提供的ILoggingBuilder。可以利用相加結果多次調用 ConfigureLogging。
var host = new HostBuilder().ConfigureLogging((hostContext, configLogging) =>
{
configLogging.AddConsole();
configLogging.AddDebug();
})
6.4.1UseConsoleLifetime
UseConsoleLifetime偵聽Ctrl+C/SIGINT或SIGTERM并調用StopApplication來啟動關閉程序。UseConsoleLifetime解除阻止RunAsync和WaitForShutdownAsync等擴充。ConsoleLifetime預注冊為預設生命周期實作,使用注冊的最後一個生命周期。
var host = new HostBuilder().UseConsoleLifetime()
7.容器配置
主機可以接受IServiceProviderFactory<TContainerBuilder>。提供工廠不屬于DI容器注冊,而是用于建立具體DI容器的主機内部函數。UseServiceProviderFactory(IServiceProviderFactory<TContainerBuilder>)重寫用于建立應用程式的服務提供程式的預設工廠。ConfigureContainer方法托管自定義容器配置。ConfigureContainer提供在基礎主機API的基礎之上配置容器的強類型體驗。可以利用相加結果多次調用ConfigureContainer。
為應用程式建立服務容器并提供服務容器工廠:
public class 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) =>{
})
8.擴充性
在IHostBuilder上使用擴充方法實作主機擴充性。應用程式建立UseHostedService擴充方法,以注冊在T中傳遞的托管服務:
public static class Extensions
{
public static IHostBuilder UseHostedService<T>(this IHostBuilder hostBuilder)
where T : class, IHostedService, IDisposable
{
return hostBuilder.ConfigureServices(services =>
services.AddHostedService<T>());
}
}
9.管理主機
IHost實作負責啟動和停止由服務容器中注冊的IHostedService實作。
9.1Run
Run運作應用程式并阻止調用線程,直到關閉主機:
public class Program
{
public void Main(string[] args)
{
var host = new HostBuilder().Build();
host.Run();
}
}
9.2RunAsync
RunAsync運作應用程式并傳回在觸發取消令牌或關閉時完成的Task:
public class Program
{
public static async Task Main(string[] args)
{
var host = new HostBuilder().Build();
await host.RunAsync();
}
}
9.3RunConsoleAsync
RunConsoleAsync啟用控制台、生成和啟動主機,以及等待Ctrl+C/SIGINT或SIGTERM關閉。
public class Program
{
public static async Task Main(string[] args)
{
var hostBuilder = new HostBuilder();
await hostBuilder.RunConsoleAsync();
}
}
9.4Start和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));
}
}
}
9.5StartAsync和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();
}
}
}
9.6WaitForShutdown
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();
}
}
}
9.7WaitForShutdownAsync
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();
}
}
}
9.8External 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));
}
}
}
在StartAsync開始時調用WaitForStartAsync,在繼續之前,會一直等待該操作完成。它可用于延遲啟動,直到外部事件發出信号。
10.IHostingEnvironment、IApplicationLifetime接口
該兩個接口類型跟上一篇Web主機IHostingEnvironment、IApplicationLifetime接口類型是一樣的,詳情就不在這多講了,想要了解的請移步到上一篇Web主機文章。
參考文獻:
ASP.NET Core 通用主機