Obecný hostitel .NET

Šablony služby Worker Service vytvářejí obecného hostitele .NET. HostBuilder Obecný hostitel lze použít s jinými typy aplikací .NET, jako jsou konzolové aplikace.

Hostitel je objekt, který zapouzdřuje prostředky a funkce životnosti aplikace, například:

  • Injektáž závislostí (DI)
  • protokolování
  • Konfigurace
  • Vypnutí aplikace
  • IHostedService Implementace

Když se hostitel spustí, volá IHostedService.StartAsync každou implementaci zaregistrované IHostedService v kolekci hostovaných služeb kontejneru služby. V aplikaci pracovních služeb se všechny implementace obsahující IHostedServiceBackgroundService instance nazývají jejich BackgroundService.ExecuteAsync metody.

Hlavním důvodem zahrnutí všech vzájemně závislých prostředků aplikace v jednom objektu je správa životnosti: kontrola nad spuštěním aplikace a bezproblémovým vypnutím. Toho dosáhnete pomocí balíčku Microsoft.Extensions.Hosting NuGet.

Nastavení hostitele

Hostitel je obvykle nakonfigurovaný, sestavený a spuštěný kódem Program ve třídě. Metoda Main :

Šablony služby .NET Worker Service vygenerují následující kód pro vytvoření obecného hostitele:

IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((hostContext, services) =>
    {
        services.AddHostedService<Worker>();
    })
    .Build();

host.Run();

Výchozí nastavení tvůrce

Metoda CreateDefaultBuilder :

  • Nastaví kořen obsahu na cestu vrácenou GetCurrentDirectory().
  • Načte konfiguraci hostitele z:
    • Proměnné prostředí s předponou DOTNET_.
    • Argumenty příkazového řádku
  • Načte konfiguraci aplikace z:
    • appsettings.json.
    • Appsettings. {Environment}.json.
    • Správce tajných kódů při spuštění aplikace v Development prostředí
    • Proměnné prostředí
    • Argumenty příkazového řádku
  • Přidá následující poskytovatele protokolování:
    • Konzola
    • Ladění
    • EventSource
    • EventLog (pouze při spuštění na Windows)
  • Povolí ověřování oboru a ověřování závislostí , pokud je Developmentprostředí .

Tato ConfigureServices metoda zpřístupňuje možnost přidávat služby do Microsoft.Extensions.DependencyInjection.IServiceCollection instance. Později je možné tyto služby zpřístupnit prostřednictvím injektáže závislostí.

Služby poskytované architekturou

Automaticky se zaregistrují následující služby:

IHostApplicationLifetime

IHostApplicationLifetime Vložte službu do libovolné třídy pro zpracování úloh po spuštění a řádném vypnutí. Tři vlastnosti rozhraní jsou tokeny zrušení používané k registraci metod spuštění aplikace a obslužné rutiny události zastavení aplikace. Rozhraní také obsahuje metodu StopApplication() .

Následující příklad je IHostedService implementace, která registruje IHostApplicationLifetime události:

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace AppLifetime.Example;

public sealed class ExampleHostedService : IHostedService
{
    private readonly ILogger _logger;

    public ExampleHostedService(
        ILogger<ExampleHostedService> logger,
        IHostApplicationLifetime appLifetime)
    {
        _logger = logger;

        appLifetime.ApplicationStarted.Register(OnStarted);
        appLifetime.ApplicationStopping.Register(OnStopping);
        appLifetime.ApplicationStopped.Register(OnStopped);
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("1. StartAsync has been called.");

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("4. StopAsync has been called.");

        return Task.CompletedTask;
    }

    private void OnStarted()
    {
        _logger.LogInformation("2. OnStarted has been called.");
    }

    private void OnStopping()
    {
        _logger.LogInformation("3. OnStopping has been called.");
    }

    private void OnStopped()
    {
        _logger.LogInformation("5. OnStopped has been called.");
    }
}

Šablonu služby Worker Service lze upravit tak, aby se přidala ExampleHostedService implementace:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using AppLifetime.Example;

using IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((_, services) =>
        services.AddHostedService<ExampleHostedService>())
    .Build();

await host.RunAsync();

Aplikace napíše následující ukázkový výstup:

// Sample output:
//     info: ExampleHostedService[0]
//           1. StartAsync has been called.
//     info: ExampleHostedService[0]
//           2. OnStarted has been called.
//     info: Microsoft.Hosting.Lifetime[0]
//           Application started.Press Ctrl+C to shut down.
//     info: Microsoft.Hosting.Lifetime[0]
//           Hosting environment: Production
//     info: Microsoft.Hosting.Lifetime[0]
//           Content root path: ..\app-lifetime\bin\Debug\net6.0
//     info: ExampleHostedService[0]
//           3. OnStopping has been called.
//     info: Microsoft.Hosting.Lifetime[0]
//           Application is shutting down...
//     info: ExampleHostedService[0]
//           4. StopAsync has been called.
//     info: ExampleHostedService[0]
//           5. OnStopped has been called.

IHostLifetime

Implementace IHostLifetime řídí, kdy se hostitel spustí a kdy se zastaví. Použije se poslední zaregistrovaná implementace. Microsoft.Extensions.Hosting.Internal.ConsoleLifetime je výchozí IHostLifetime implementace. Další informace o mechanikě životnosti vypnutí najdete v tématu Vypnutí hostitele.

IHostEnvironment

IHostEnvironment Vložte službu do třídy, abyste získali informace o následujících nastaveních:

Konfigurace hostitele

Konfigurace hostitele slouží ke konfiguraci vlastností implementace IHostEnvironment .

Konfigurace hostitele je dostupná v nástroji HostBuilderContext.Configuration v rámci ConfigureAppConfiguration metody. Při volání ConfigureAppConfiguration metody, a IConfigurationBuilder jsou předány HostBuilderContext do configureDelegate. Je configureDelegate definován jako Action<HostBuilderContext, IConfigurationBuilder>. Kontext tvůrce hostitelů zpřístupňuje Configuration vlastnost, což je instance IConfiguration. Představuje konfiguraci vytvořenou z hostitele, zatímco IConfigurationBuilder objekt tvůrce použitý ke konfiguraci aplikace.

Tip

Po ConfigureAppConfiguration zavolání HostBuilderContext.Configuration se nahradí konfigurací aplikace.

Pokud chcete přidat konfiguraci hostitele, zavolejte ConfigureHostConfiguration .IHostBuilder ConfigureHostConfiguration lze volat vícekrát s doplňkovými výsledky. Hostitel používá jakoukoli možnost, která nastaví hodnotu poslední na daném klíči.

Následující příklad vytvoří konfiguraci hostitele:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;

using IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureHostConfiguration(configHost =>
    {
        configHost.SetBasePath(Directory.GetCurrentDirectory());
        configHost.AddJsonFile("hostsettings.json", optional: true);
        configHost.AddEnvironmentVariables(prefix: "PREFIX_");
        configHost.AddCommandLine(args);
    })
    .Build();

// Application code should start here.

await host.RunAsync();

Konfigurace aplikací

Konfigurace aplikace se vytvoří voláním ConfigureAppConfigurationIHostBuilder. ConfigureAppConfiguration lze volat vícekrát s doplňkovými výsledky. Aplikace používá jakoukoli možnost, která nastaví hodnotu poslední na daném klíči.

Konfigurace vytvořená nástrojem ConfigureAppConfigurationHostBuilderContext.Configuration je k dispozici pro následné operace a jako službu z DI. Konfigurace hostitele se také přidá do konfigurace aplikace.

Další informace najdete v tématu Konfigurace v .NET.

Vypnutí hostitele

Hostovaný proces služby se dá zastavit následujícími způsoby:

Všechny tyto scénáře se nezpracují přímo hostitelským kódem. Vlastník procesu se s nimi musí vypořádat stejně jako s libovolnou aplikací. Existuje několik dalších způsobů, jak lze zastavit hostovaný proces služby:

  • Pokud ConsoleLifetime se používá, naslouchá následujícím signálům a pokusí se hostitele elegantně zastavit.
    • SIGINT (nebo CTRL+C).
    • SIGQUIT (nebo CTRL+BREAK na Windows, CTRL+\ v Unixu).
    • SIGTERM (odesílaný jinými aplikacemi, například docker stop).
  • Pokud aplikace volá Environment.Exit.

Tyto scénáře se zpracovávají integrovanou logikou hostování, konkrétně ConsoleLifetime třídou. ConsoleLifetime snaží se zpracovat signály SIGINT, SIGQUIT a SIGTERM, aby umožňovaly řádné ukončení aplikace.

Před .NET 6 nebyl způsob, jak kód .NET správně zpracovat SIGTERM. Chcete-li toto omezení obejít, ConsoleLifetime přihlaste se k odběru System.AppDomain.ProcessExit. Když ProcessExit byl vyvolán, ConsoleLifetime signalizovalo by hostiteli, aby zastavil a zablokoval ProcessExit vlákno a čekalo na zastavení hostitele. To by umožnilo, aby se kód v aplikaci spustil , například IHost.StopAsync a kód za HostingAbstractionsHostExtensions.Run metodou Main .

To způsobilo další problémy, protože SIGTERM nebyl jediným způsobem, jak ProcessExit byl vyvolán. Také je vyvolán kódem ve volání Environment.Exitaplikace . Environment.Exit není elegantní způsob vypnutí procesu v Microsoft.Extensions.Hosting modelu aplikace. ProcessExit Vyvolá událost a pak proces ukončí. Konec Main metody se nespustí. Vlákna pozadí a popředí jsou ukončena a finally bloky se nespustí .

Vzhledem k ConsoleLifetime tomu, že blokované ProcessExit při čekání na vypnutí hostitele, toto chování vedlo k zablokování z Environment.Exit také bloků čekajících na volání ProcessExit. Kromě toho, protože zpracování SIGTERM se pokusilo tento proces řádně vypnout, ConsoleLifetime nastavilo ExitCode by to na 0, který zaplnil ukončovací kód uživatele předaný Environment.Exit.

V .NET 6 se podporují a zpracovávají signály POSIX . To umožňuje ConsoleLifetime zpracovávat SIGTERM elegantně a už se při vyvolání nezapojovat Environment.Exit .

Tip

Pro .NET 6+ ConsoleLifetime už nemá logiku pro zpracování scénáře Environment.Exit. Aplikace, které volají Environment.Exit a potřebují provádět logiku vyčištění, se můžou přihlásit k ProcessExit odběru sami. Hostování se už nebude pokoušet o řádné zastavení hostitele v tomto scénáři.

Pokud vaše aplikace používá hostování a chcete hostitele elegantně zastavit, můžete volat IHostApplicationLifetime.StopApplication místo Environment.Exit.

Proces vypnutí hostování

Následující posloupnostový diagram ukazuje, jak se signály interně zpracovávají v hostitelském kódu. Většina uživatelů tento proces nemusí pochopit. Ale pro vývojáře, kteří potřebují hluboké porozumění, vám to může pomoct začít.

Po spuštění hostitele se při volání Run uživatele nebo WaitForShutdownobslužné rutině zaregistruje .IApplicationLifetime.ApplicationStopping Spuštění se pozastaví a WaitForShutdownčeká na vyvolání ApplicationStopping události. Tímto způsobem Main se metoda hned nevrací a aplikace zůstane spuštěná, dokud Run se nevrátí nebo WaitForShutdown se vrátí.

Když se do procesu odešle signál, spustí se následující sekvence:

Hosting shutdown sequence diagram.

  1. Řídicí toky od ConsoleLifetime k ApplicationLifetime vyvolání ApplicationStopping události. To signalizuje WaitForShutdownAsync odblokování spouštěcího Main kódu. Mezitím se obslužná rutina signálu POSIX vrátí Cancel = true od zpracování tohoto signálu POSIX.
  2. Main Spouštěcí kód se spustí znovu a řekne hostiteliStopAsync(), kterému se zase zastaví všechny hostované služby a vyvolá všechny ostatní zastavené události.
  3. WaitForShutdown Nakonec ukončete, což umožňuje, aby všechny aplikace uklidily kód, aby se spustil, a Main aby metoda mohla elegantně ukončit.

Viz také