Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Návod
Tento obsah je výňatek z eBooku, architektury mikroslužeb .NET pro kontejnerizované aplikace .NET, které jsou k dispozici na .NET Docs nebo jako zdarma ke stažení PDF, které lze číst offline.
Úlohy na pozadí a naplánované úlohy jsou něco, co může být potřeba použít v jakékoli aplikaci, ať už se řídí vzorem architektury mikroslužeb. Rozdíl při použití architektury mikroslužeb spočívá v tom, že úlohu na pozadí můžete implementovat v samostatném procesu nebo kontejneru pro hostování, abyste ji mohli podle potřeby škálovat dolů/nahoru.
Z obecného hlediska jsme v .NET nazvali tento typ úloh hostovaných služeb, protože se jedná o služby/logiku hostující v rámci hostitele, aplikace nebo mikroslužby. Všimněte si, že v tomto případě hostovaná služba jednoduše představuje třídu obsahující logiku úloh běžících na pozadí.
Od verze .NET Core 2.0 framework poskytuje nové rozhraní IHostedService, které vám usnadní implementaci hostovaných služeb. Základní myšlenkou je, že můžete zaregistrovat několik úloh na pozadí využívajících hostované služby, které probíhají, zatímco váš webový server nebo hostitel funguje, jak je znázorněno na obrázku 6–26.
Obrázek 6–26 Použití služby IHostedService ve webovém hostiteli vs. hostitele
ASP.NET Core 1.x a 2.x podporuje IWebHost pro procesy na pozadí ve webových aplikacích. .NET Core 2.1 a novější verze podporují IHost procesy na pozadí s prostými konzolovými aplikacemi. Všimněte si rozdílu mezi WebHost a Host.
A WebHost (základní třída implementující IWebHost) v ASP.NET Core 2.0 je prvek infrastruktury, který slouží k poskytování funkcí serveru HTTP procesu, například při implementaci webové aplikace MVC nebo webové API služby. Poskytuje veškerou novou infrastrukturu v ASP.NET Core, která umožňuje používat injektáž závislostí, vkládat middlewary do kanálu žádosti a podobně. Tyto WebHost se používají stejně IHostedServices pro úlohy na pozadí.
V .NET Core 2.1 byla zavedena základní třída Host, která implementuje IHost. V podstatě vám Host umožňuje mít podobnou infrastrukturu, jako máte s WebHost (injektáž závislostí, hostované služby atd.), ale v tomto případě chcete mít jednoduchý a lehčí proces, který slouží jako hostitel, bez prvků souvisejících s MVC, webovým rozhraním API nebo serverem HTTP.
Proto můžete zvolit a buď vytvořit specializovaný hostitelský proces IHost pro zpracování hostovaných služeb a nic jiného, jako je mikroslužba vytvořená jen pro hostování IHostedServices, nebo můžete případně rozšířit existující ASP.NET Core WebHost, jako je existující webové rozhraní API ASP.NET Core nebo aplikace MVC.
Každý přístup má výhody a nevýhody v závislosti na potřebách vaší firmy a škálovatelnosti. Dolní řádek je v podstatě to, že pokud vaše úlohy na pozadí nemají nic společného s HTTP (IWebHost), byste měli použít IHost.
Registrace hostovaných služeb ve webovém hostiteli nebo hostiteli
Pojďme se podrobněji zaměřit na rozhraní IHostedService, protože jeho použití je docela podobné v WebHost nebo v Host.
SignalR je jedním z příkladů artefaktu, který používá hostované služby, ale můžete ho také použít pro mnohem jednodušší věci, jako například:
- Úloha na pozadí průběžně kontroluje databázi a hledá změny.
- Naplánovaná úloha pravidelně aktualizuje určitou mezipaměť.
- Implementace QueueBackgroundWorkItem, která umožňuje spuštění úlohy ve vlákně na pozadí.
- Zpracování zpráv z fronty zpráv na pozadí webové aplikace při sdílení společných služeb, jako je
ILogger. - Úloha na pozadí byla spuštěna s
Task.Run().
V podstatě můžete některou z těchto akcí přesměrovat na úlohu na pozadí, která implementuje IHostedService.
Způsob, jak přidat jeden nebo více IHostedServices do svého WebHost nebo Host, je jejich registrace pomocí rozšiřující metody AddHostedService v ASP.NET Core WebHost (nebo v Host v .NET Core 2.1 a vyšším). V podstatě musíte v Program.cs zaregistrovat hostované služby v rámci spuštění aplikace.
//Other DI registrations;
// Register Hosted Services
builder.Services.AddHostedService<GracePeriodManagerService>();
builder.Services.AddHostedService<MyHostedServiceB>();
builder.Services.AddHostedService<MyHostedServiceC>();
//...
V takovém kódu je GracePeriodManagerService hostovaná služba skutečným kódem z objednávkové mikroslužby v eShopOnContainers, zatímco další dva jsou jen ukázkové příklady.
Provádění úlohy běžící na pozadí je koordinované s životním cyklem aplikace (ať už hostitele nebo mikroslužby). Když se aplikace spustí, zaregistrujete úlohy a máte možnost provést nějakou elegantní akci nebo vyčistit, když se aplikace vypne.
Bez použití IHostedServicebyste mohli vždy spustit vlákno na pozadí ke spuštění libovolné úlohy. Rozdíl je přesně v době vypnutí aplikace, kdy by se toto vlákno jednoduše zabilo, aniž by bylo možné spouštět řádné akce čištění.
Rozhraní IHostedService
Při registraci IHostedService volá rozhraní .NET při spuštění aplikace metodu StartAsync() a při zastavení metodu StopAsync() vašeho typu IHostedService. Další podrobnosti najdete v rozhraní IHostedService.
Jak si můžete představit, můžete vytvořit více implementací IHostedService a zaregistrovat každý z nich v Program.cs, jak je znázorněno dříve. Všechny hostované služby se spustí a zastaví spolu s aplikací nebo mikroslužbou.
Jako vývojář jste zodpovědní za řízení procesu zastavení vašich služeb, když hostitel vyvolá StopAsync() metodu.
Implementace IHostedService s vlastní hostovanou třídou služby, která je odvozena ze základní třídy BackgroundService
Můžete pokračovat a vytvořit vlastní hostovanou třídu služby od začátku a implementovat IHostedService, jak je potřeba udělat při použití .NET Core 2.0 a novější.
Vzhledem k tomu, že většina úloh na pozadí bude mít podobné potřeby týkající se správy tokenů zrušení a dalších typických operací, existuje praktická abstraktní základní třída, ze které můžete odvodit název BackgroundService (k dispozici od .NET Core 2.1).
Tato třída zajišťuje hlavní funkci potřebnou pro nastavení úlohy na pozadí.
Dalším kódem je abstraktní základní třída BackgroundService, jak je implementována v .NET.
// Copyright (c) .NET Foundation. Licensed under the Apache License, Version 2.0.
/// <summary>
/// Base class for implementing a long running <see cref="IHostedService"/>.
/// </summary>
public abstract class BackgroundService : IHostedService, IDisposable
{
private Task _executingTask;
private readonly CancellationTokenSource _stoppingCts =
new CancellationTokenSource();
protected abstract Task ExecuteAsync(CancellationToken stoppingToken);
public virtual Task StartAsync(CancellationToken cancellationToken)
{
// Store the task we're executing
_executingTask = ExecuteAsync(_stoppingCts.Token);
// If the task is completed then return it,
// this will bubble cancellation and failure to the caller
if (_executingTask.IsCompleted)
{
return _executingTask;
}
// Otherwise it's running
return Task.CompletedTask;
}
public virtual async Task StopAsync(CancellationToken cancellationToken)
{
// Stop called without start
if (_executingTask == null)
{
return;
}
try
{
// Signal cancellation to the executing method
_stoppingCts.Cancel();
}
finally
{
// Wait until the task completes or the stop token triggers
await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite,
cancellationToken));
}
}
public virtual void Dispose()
{
_stoppingCts.Cancel();
}
}
Při odvození z předchozí abstraktní základní třídy stačí díky této zděděné implementaci implementovat metodu ExecuteAsync() ve své vlastní třídě hostované služby, stejně jako v následujícím zjednodušeném kódu z eShopOnContainers, který provádí dotazy na databázi a publikuje události integrace na Event Bus v případě potřeby.
public class GracePeriodManagerService : BackgroundService
{
private readonly ILogger<GracePeriodManagerService> _logger;
private readonly OrderingBackgroundSettings _settings;
private readonly IEventBus _eventBus;
public GracePeriodManagerService(IOptions<OrderingBackgroundSettings> settings,
IEventBus eventBus,
ILogger<GracePeriodManagerService> logger)
{
// Constructor's parameters validations...
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogDebug($"GracePeriodManagerService is starting.");
stoppingToken.Register(() =>
_logger.LogDebug($" GracePeriod background task is stopping."));
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogDebug($"GracePeriod task doing background work.");
// This eShopOnContainers method is querying a database table
// and publishing events into the Event Bus (RabbitMQ / ServiceBus)
CheckConfirmedGracePeriodOrders();
try {
await Task.Delay(_settings.CheckUpdateTime, stoppingToken);
}
catch (TaskCanceledException exception) {
_logger.LogCritical(exception, "TaskCanceledException Error", exception.Message);
}
}
_logger.LogDebug($"GracePeriod background task is stopping.");
}
.../...
}
V tomto konkrétním případě pro eShopOnContainers se provádí metoda aplikace, která dotazuje tabulku databáze a vyhledává objednávky s určitým stavem. Při provádění změn zveřejňuje integrační události přes sběrnici událostí, přičemž může používat RabbitMQ nebo Azure Service Bus.
Samozřejmě můžete místo toho spustit jakoukoli jinou úlohu na pozadí firmy.
Ve výchozím nastavení je token zrušení nastaven s časovým limitem 5 sekund, i když tuto hodnotu můžete změnit při sestavování WebHost pomocí rozšíření UseShutdownTimeoutIWebHostBuilder. To znamená, že se očekává, že dojde k zrušení služby do 5 sekund, jinak bude náhle ukončena.
Následující kód by tento čas změnil na 10 sekund.
WebHost.CreateDefaultBuilder(args)
.UseShutdownTimeout(TimeSpan.FromSeconds(10))
...
Souhrnný třídní diagram
Následující obrázek znázorňuje vizuální souhrn tříd a rozhraní zahrnutých při implementaci IHostedServices.
Obrázek 6–27 Diagram tříd znázorňující více tříd a rozhraní souvisejících s IHostedService
Diagram tříd: IWebHost a IHost mohou hostovat mnoho služeb, které dědí z BackgroundService, které implementují IHostedService.
Aspekty nasazení a poznatky
Je důležité si uvědomit, že způsob nasazení ASP.NET Core WebHost nebo .NET Host může mít vliv na konečné řešení. Pokud například nasadíte WebHost na IIS nebo běžnou službu Azure App Service, váš hostitel může být vypnut kvůli recyklaci fondu aplikací. Pokud ale nasazujete hostitele jako kontejner do orchestrátoru, jako je Kubernetes, můžete řídit ujištěný počet živých instancí hostitele. Kromě toho byste mohli zvážit i další přístupy v cloudu, zejména pro tyto scénáře, jako je Azure Functions. A konečně, pokud potřebujete, aby služba běžela neustále a nasazujete na Windows Server, můžete použít službu systému Windows.
I když je-li nasazen WebHost do fondu aplikací, existují scénáře, jako je opětovné naplnění nebo vyprázdnění mezipaměti aplikace v operační paměti, které by stále platily.
Rozhraní IHostedService poskytuje pohodlný způsob, jak spustit úlohy na pozadí ve webové aplikaci ASP.NET Core (v .NET Core 2.0 a novějších verzích) nebo v jakémkoli procesu nebo hostiteli (počínaje verzí .NET Core 2.1 s IHost). Jeho hlavní výhodou je příležitost, kterou získáte se stylovým zrušením úloh, abyste vyčistili kód úloh běžících na pozadí, když se hostitel sám ukončuje.
Dodatečné zdroje
Sestavení naplánované úlohy v ASP.NET Core/Standard 2.0
https://blog.maartenballiauw.be/post/2017/08/01/building-a-scheduled-cache-updater-in-aspnet-core-2.htmlImplementace IHostedService v ASP.NET Core 2.0
https://www.stevejgordon.co.uk/asp-net-core-2-ihostedserviceGenericHost Sample using ASP.NET Core 2.1
https://github.com/aspnet/Hosting/tree/release/2.1/samples/GenericHostSample