.NET 通用主機

2019-04-17 08:58 更新

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 中設置控制臺:

  1. 打開 .vscode/launch.json 文件。
  2. 在 .NET Core 啟動(控制臺)配置中,找到控制臺條目。 將值設置為 externalTerminal 或 integratedTerminal。

介紹

通用主機庫位于 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)容根

此設置確定主機從哪里開始搜索內(nèi)容文件。

鍵:contentRoot類型:string默認值:默認為應用程序集所在的文件夾。設置使用:UseContentRoot環(huán)境變量:<PREFIX_>CONTENTROOT(<PREFIX_> 是用戶定義的可選前綴

如果路徑不存在,主機將無法啟動。

C#

var host = new HostBuilder()
    .UseContentRoot("c:\\<content-root>")

環(huán)境

設置應用的環(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

ConfigureHostConfiguration 使用 IConfigurationBuilder 來為主機創(chuàng)建 IConfiguration。 主機配置用于初始化 IHostingEnvironment,以供在應用的構建過程中使用。

可多次調(diào)用 ConfigureHostConfiguration,并得到累計結果。 主機使用上一次在一個給定鍵上設置值的選項。

主機配置自動流向應用配置(ConfigureAppConfiguration 和應用的其余部分)。

默認情況下不包括提供程序。 必須在 ConfigureHostConfiguration 中顯式指定應用所需的任何配置提供程序,包括:

  • 文件配置(例如,來自 hostsettings.json 文件)。
  • 環(huán)境變量配置。
  • 命令行參數(shù)配置。
  • 任何其他所需的配置提供程序。

通過使用 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);
    })

ConfigureAppConfiguration

通過在 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

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

ConfigureLogging 添加了一個委托來配置提供的 ILoggingBuilder。 可以利用相加結果多次調(diào)用 ConfigureLogging。

C#

var host = new HostBuilder()
    .ConfigureLogging((hostContext, configLogging) =>
    {
        configLogging.AddConsole();
        configLogging.AddDebug();
    })

UseConsoleLifetime

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

RunAsync 運行應用并返回在觸發(fā)取消令牌或關閉時完成的 Task

C#

public class Program
{
    public static async Task Main(string[] args)
    {
        var host = new HostBuilder()
            .Build();

        await host.RunAsync();
    }
}

RunConsoleAsync

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

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

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

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

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 接口

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 接口

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();
    }
}


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號