1. 程式人生 > >(16)ASP.NET Core 通用主機(HostBuilder)

(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 通用