一.概述
ASP.NET Core 通用主機 (HostBuilder),該主機對於托管不處理 HTTP 請求的應用非常有用。通用主機的目標是將 HTTP 管道從 Web 主機 API 中分離出來,從而啟用更多的主機方案。 基於通用主機的消息、后台任務和其他非 HTTP 工作負載可從橫切功能(如配置、依賴關系注入 [DI] 和日志記錄)中受益。通用主機是 ASP.NET Core 2.1 中的新增功能,不適用於 Web 承載方案。通用主機正處於開發階段,用於在未來版本中替換 Web 主機,並在 HTTP 和非 HTTP 方案中充當主要的主機 API。
通用主機庫位於 Microsoft.Extensions.Hosting 命名空間中,而web主機庫位於Microsoft.AspNetCore.Hosting命令空間中。
PM> Install-Package Microsoft.AspNetCore.Hosting.Abstractions -Version 2.2.0
1.1 設置主機
IHostBuilder 是供庫和應用初始化、生成和運行主機的主要組件。(官方文檔中main方法是使用的異步,但本人vs程序啟動時提示找不到mian方法,只好改成了同步) 。
public static void Main(string[] args) { var host = new HostBuilder() .Build(); host.Run(); }
1.2 默認服務
在主機初始化期間注冊以下服務:
環境 (IHostingEnvironment)
HostBuilderContext
配置 (IConfiguration)
IApplicationLifetime (ApplicationLifetime)
IHostLifetime (ConsoleLifetime)
IHost
選項 (AddOptions)
日志記錄 (AddLogging)
1.3 主機配置 ConfigureHostConfiguration
主機配置的創建方式如下:
調用 IHostBuilder 上的擴展方法以設置“內容根”和“環境”。
從 ConfigureHostConfiguration 中的配置提供程序讀取配置。
(1) ConfigureHostConfiguration 主機配置
通用主機配置與web主機配置還是有些區別,在通用主機中有ConfigureHostConfiguration用來配置主機。主機配置用於初始化 IHostingEnvironment,以供在應用的構建過程中使用。可多次調用 ConfigureHostConfiguration,並得到累計結果。必須在 ConfigureHostConfiguration 中顯式指定應用所需的任何配置提供程序,包括:
1)文件配置(例如,來自 hostsettings.json 文件)。
2)環境變量配置。
3)命令行參數配置。
4)任何其他所需的配置提供程序。
通過使用 SetBasePath 指定應用的基本路徑,然后調用其中一個文件配置提供程序,可以啟用主機的文件配置。
(2) AddEnvironmentVariables 環境變量
要添加主機的環境變量配置,請在主機生成器上調用 AddEnvironmentVariables。 示例應用使用前綴 PREFIX_。 當系統讀取環境變量時,便會刪除前綴。 配置示例應用的主機后,PREFIX_ENVIRONMENT 的環境變量值就變成 environment密鑰的主機配置值。
(3) AddCommandLine 命令行參數
通過 dotnet run 運行應用 指定參數時,通過調用 AddCommandLine 可添加命令行配置。
1.4 應用配置 ConfigureAppConfiguration
調用 ConfigureAppConfiguration 創建應用配置,在web主機中也有介紹。這里就不再說明。 主機配置和應用配置都可以做配置使用,主機配置重點在主機環境的配置(IHostingEnvironment)。
1.5 ConfigureServices
ConfigureServices 將服務添加到應用的依賴關系注入容器。 可多次調用 ConfigureServices,並得到累計結果。這個在web主機中常用。 值得注意的是:除了三種注入的實例生命周期(asp.net core 系列 4 注入服務的生存期)。還可以注入THostedService類型服務,專門用於做后台服務的。
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>(); })
1.6 IApplicationLifetime 接口
IApplicationLifetime接口在上篇介紹web主機進有講過,這里不在具體介紹。下面會有代碼演示,實現一個IHostedService類型服務,在服務中用於注冊事件。
二. 完整示例
使用通用主機來演示一個后台服務。使用控制台做宿主,后台服務定時每隔5秒執行一次。該演示包括主機配置、應用配置、服務容器注入、日志配置。還包括注入二個IHostedService類型的服務。其中TimedHostedService類用於做后台定時服務,LifetimeEventsHostedService類注入服務IApplicationLifetime事件,監聽服務運行狀態。
完整示例github地址:
public class Program { /// <summary> /// 使用控制台做承載的后台服務 /// </summary> /// <param name="args"></param> public static void Main(string[] args) { var host = new HostBuilder() .ConfigureHostConfiguration(configHost => { configHost.SetBasePath(Directory.GetCurrentDirectory()); configHost.AddJsonFile("hostsettings.json", optional: true); configHost.AddEnvironmentVariables(prefix: "PREFIX_"); configHost.AddCommandLine(args); }) .ConfigureAppConfiguration((hostContext, configApp) => { configApp.AddJsonFile("appsettings.json", optional: true); configApp.AddJsonFile( $"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true); configApp.AddEnvironmentVariables(prefix: "PREFIX_"); configApp.AddCommandLine(args); }) .ConfigureServices((hostContext, services) => { //注冊后台普通服務 // services.AddSingleton<IJobTimeService, JobTimeService>(); //注冊后台THostedService類型服務 services.AddHostedService<LifetimeEventsHostedService>(); services.AddHostedService<TimedHostedService>(); }) .ConfigureLogging((hostContext, configLogging) => { configLogging.AddConsole(); configLogging.AddDebug(); }) .UseConsoleLifetime() .Build(); //實例化注入的普通服務 // IJobTimeService job = host.Services.GetRequiredService<IJobTimeService>(); // job.Time(); host.Run(); } }
/// <summary> ///監聽服務運行狀態 /// </summary> 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 } }
/// <summary> /// 后台定時服務 /// </summary> internal class TimedHostedService : IHostedService, IDisposable { private readonly ILogger _logger; private Timer _timer; public TimedHostedService(ILogger<TimedHostedService> logger) { _logger = logger; } public Task StartAsync(CancellationToken cancellationToken) { _logger.LogInformation("Timed Background Service is starting."); _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5)); return Task.CompletedTask; } /// <summary> /// 每隔5秒執行一次 /// </summary> /// <param name="state"></param> private void DoWork(object state) { _logger.LogInformation("Timed Background Service is working."); } public Task StopAsync(CancellationToken cancellationToken) { _logger.LogInformation("Timed Background Service is stopping."); _timer?.Change(Timeout.Infinite, 0); return Task.CompletedTask; } public void Dispose() { _timer?.Dispose(); } }
-- hostsettings.json文件 { "environment": "Development" }
參考文獻:
官方文檔:ASP.NET Core 通用主機
