IHostedService ve BackgroundService sınıfıyla mikro hizmetlerde arka plan görevleri uygulama
İpucu
Bu içerik, .NET Docs'ta veya çevrimdışı olarak okunabilen ücretsiz indirilebilir bir PDF olarak sağlanan Kapsayıcılı .NET Uygulamaları için .NET Mikro Hizmet Mimarisi e-Kitabı'ndan bir alıntıdır.
Arka plan görevleri ve zamanlanmış işler, mikro hizmet mimarisi desenine uygun olsun veya olmasın, herhangi bir uygulamada kullanmanız gerekebilecek bir şeydir. Mikro hizmetler mimarisini kullanırkenki fark, arka plan görevini barındırma için ayrı bir işlemde/kapsayıcıda uygulayabilmeniz ve böylece ihtiyacınıza göre ölçeğini azaltabilmeniz/artırabilmenizdir.
Genel bir bakış açısından, .NET'te bu tür görevleri Barındırılan Hizmetler olarak adlandırdık çünkü bunlar konak/uygulama/mikro hizmetinizde barındırdığınız hizmetler/mantıklar. Bu durumda barındırılan hizmetin yalnızca arka plan görev mantığına sahip bir sınıf anlamına geldiğini unutmayın.
.NET Core 2.0 sürümünden bu yana çerçeve, barındırılan hizmetleri kolayca uygulamanıza yardımcı olmak için adlı IHostedService yeni bir arabirim sağlar. Temel fikir, 6-26 arası görüntüde gösterildiği gibi web konağınız veya konağınız çalışırken arka planda çalışan birden çok arka plan görevini (barındırılan hizmetler) kaydedebilmenizdir.
Şekil 6-26. WebHost'ta IHostedService kullanma ve Konak karşılaştırması
web uygulamalarında arka plan işlemleri için Core 1.x ve 2.x desteği IWebHost
ASP.NET. .NET Core 2.1 ve sonraki sürümleri, düz konsol uygulamalarıyla arka plan işlemlerini destekler IHost
. ve Host
arasında WebHost
yapılan farka dikkat edin.
WebHost
ASP.NET Core 2.0'daki bir (temel sınıf uygulayanIWebHost
), bir MVC web uygulaması veya Web API hizmeti uygularken olduğu gibi, işleminize HTTP sunucusu özellikleri sağlamak için kullandığınız altyapı yapıtıdır. ASP.NET Core'da tüm yeni altyapı iyiliğini sağlayarak bağımlılık ekleme, istek işlem hattına ara yazılım ekleme ve benzeri işlemleri kullanmanıza olanak tanır. , WebHost
arka plan görevleri için bunları çok aynı IHostedServices
şekilde kullanır.
Host
.NET Core 2.1'de bir (temel sınıf uygulayanIHost
) kullanıma sunulmuştur. Temel olarak, a Host
ile sahip WebHost
olduğunuzdan (bağımlılık ekleme, barındırılan hizmetler vb.) benzer bir altyapıya sahip olmanıza olanak tanır, ancak bu durumda, MVC, Web API veya HTTP sunucusu özellikleriyle ilgili hiçbir şey olmadan konak olarak basit ve daha açık bir işleme sahip olmak istersiniz.
Bu nedenle, barındırılan hizmetleri işlemek için özel bir konak işlemi IHost
seçebilir ve oluşturabilirsiniz; yalnızca barındırmak için IHostedServices
yapılmış bir mikro hizmet gibi başka bir şey değil ya da alternatif olarak mevcut ASP.NET Core Web API'si veya MVC uygulaması gibi mevcut bir ASP.NET Core'u WebHost
genişletebilirsiniz.
Her yaklaşımın, iş ve ölçeklenebilirlik gereksinimlerinize bağlı olarak avantajları ve dezavantajları vardır. Özetle, arka plan görevlerinizin HTTP (IWebHost
) ile hiçbir ilgisi yoksa kullanmanız IHost
gerekir.
Barındırılan hizmetleri WebHost'unuza veya Konağınıza kaydetme
kullanımı veya içinde oldukça benzer olduğundan arabirimde WebHost
Host
daha fazla IHostedService
detaya gidelim.
SignalR, barındırılan hizmetleri kullanan bir yapıtın bir örneğidir, ancak bunu aşağıdakiler gibi çok daha basit şeyler için de kullanabilirsiniz:
- Değişiklikleri arayan bir veritabanını yoklayan bir arka plan görevi.
- Belirli aralıklarla önbellek güncelleştirilen zamanlanmış bir görev.
- Bir görevin arka plan iş parçacığında yürütülmesine izin veren QueueBackgroundWorkItem uygulaması.
- gibi
ILogger
yaygın hizmetleri paylaşırken bir web uygulamasının arka planında ileti kuyruğundan gelen iletileri işleme. - ile
Task.Run()
başlatılan bir arka plan görevi.
Bu eylemlerden herhangi birini uygulayan IHostedService
bir arka plan görevine boşaltabilirsiniz.
veya içine Host
WebHost
bir veya birden çok IHostedServices
ekleme yöntemi, uzantı yöntemi aracılığıyla AddHostedService bunları bir ASP.NET Core'a (veya .NET Core WebHost
2.1 ve üzeri bir Host
içinde) kaydetmektir. Temel olarak, barındırılan hizmetleri uygulama başlatma içinde Program.cs'a kaydetmeniz gerekir.
//Other DI registrations;
// Register Hosted Services
builder.Services.AddHostedService<GracePeriodManagerService>();
builder.Services.AddHostedService<MyHostedServiceB>();
builder.Services.AddHostedService<MyHostedServiceC>();
//...
Bu kodda barındırılan GracePeriodManagerService
hizmet, eShopOnContainers'daki Ordering iş mikro hizmetinden alınan gerçek koddur, diğer ikisi ise yalnızca iki ek örnektir.
Arka IHostedService
plan görevi yürütme, uygulamanın yaşam süresiyle (konak veya mikro hizmet) eşgüdümlüdür. Uygulama başlatıldığında görevleri kaydedersiniz ve uygulama kapatılırken düzgün bir eylem veya temizleme yapma fırsatınız olur.
kullanmadan IHostedService
, herhangi bir görevi çalıştırmak için her zaman bir arka plan iş parçacığı başlatabilirsiniz. Aradaki fark, bu iş parçacığının düzgün temizleme eylemleri çalıştırma fırsatına sahip olmadan basitçe öldürüleceği uygulamanın kapatma süresidir.
IHostedService arabirimi
Bir IHostedService
kaydettiğinizde , .NET sırasıyla uygulama başlatma ve durdurma sırasında türünüzün IHostedService
ve StopAsync()
yöntemlerini çağırırStartAsync()
. Diğer ayrıntılar için bkz . IHostedService arabirimi.
Tahmin edebileceğiniz gibi, daha önce gösterildiği gibi birden çok IHostedService uygulaması oluşturabilir ve bunların her birini Program.cs kaydedebilirsiniz. Tüm bu barındırılan hizmetler, uygulama/mikro hizmetle birlikte başlatılır ve durdurulur.
Bir geliştirici olarak, konak tarafından yöntem tetiklendiğinde StopAsync()
hizmetlerinizin durdurma eylemini işlemek sizin sorumluluğunuzdadır.
BackgroundService temel sınıfından türetilen özel bir barındırılan hizmet sınıfıyla IHostedService uygulama
Devam edip sıfırdan özel barındırılan hizmet sınıfınızı oluşturabilir ve .NET Core 2.0 ve üzerini kullanırken yapmanız gereken şekilde uygulamasını gerçekleştirebilirsiniz IHostedService
.
Ancak, çoğu arka plan görevinin iptal belirteçleri yönetimi ve diğer tipik işlemler açısından benzer gereksinimleri olacağından, türetebileceğiniz uygun bir soyut temel sınıf vardır( BackgroundService
.NET Core 2.1'den itibaren kullanılabilir).
Bu sınıf, arka plan görevini ayarlamak için gereken ana çalışmayı sağlar.
Sonraki kod, .NET'te uygulandığı gibi soyut BackgroundService temel sınıfıdır.
// 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();
}
}
Önceki soyut temel sınıftan türetilirken, devralınan uygulama sayesinde, gerektiğinde veritabanını yoklayan ve Event Bus'a tümleştirme olayları yayımlayan eShopOnContainers'dan aşağıdaki basitleştirilmiş kodda olduğu gibi yöntemini kendi özel barındırılan hizmet sınıfınızda uygulamanız ExecuteAsync()
yeterlidir.
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.");
}
.../...
}
eShopOnContainers için bu özel durumda, belirli bir duruma sahip siparişleri arayan bir veritabanı tablosunu sorgulayan bir uygulama yöntemi yürütür ve değişiklikleri uygularken olay veri yolu aracılığıyla tümleştirme olayları yayımlar (altında RabbitMQ veya Azure Service Bus kullanılabilir).
Elbette, bunun yerine başka bir iş arka planı görevi çalıştırabilirsiniz.
varsayılan olarak, iptal belirteci 5 saniyelik bir zaman aşımı ile ayarlanır, ancak uzantısını IWebHostBuilder
kullanarak UseShutdownTimeout
bu değeri değiştirebilirsinizWebHost
. Bu, hizmetimizin 5 saniye içinde iptal edilmesi beklendiği anlamına gelir, aksi takdirde daha ani bir şekilde sonlandırılır.
Aşağıdaki kod bu süreyi 10 saniye olarak değiştirir.
WebHost.CreateDefaultBuilder(args)
.UseShutdownTimeout(TimeSpan.FromSeconds(10))
...
Özet sınıf diyagramı
Aşağıdaki görüntüde IHostedServices uygulanırken kullanılan sınıfların ve arabirimlerin görsel bir özeti gösterilmektedir.
Şekil 6-27. IHostedService ile ilgili birden çok sınıfı ve arabirimi gösteren sınıf diyagramı
Sınıf diyagramı: IWebHost ve IHost, IHostedService uygulayan BackgroundService'ten devralınan birçok hizmeti barındırabilir.
Dağıtımla ilgili dikkat edilmesi gerekenler ve dikkat edilmesi gerekenler
ASP.NET Core'unuzu WebHost
veya .NET'inizi Host
dağıtma yönteminizin son çözümü etkileyebileceklerini unutmayın. Örneğin, IIS veya normal bir Azure Uygulaması Hizmeti'ne dağıtıyorsanız WebHost
uygulama havuzu geri dönüşümleri nedeniyle konağınız kapatılabilir. Ancak konağınızı Kubernetes gibi bir düzenleyiciye kapsayıcı olarak dağıtıyorsanız konağınızın canlı örneklerinin sayısını denetleyebilirsiniz. Buna ek olarak, bulutta özellikle bu senaryolar için yapılan Azure İşlevleri gibi diğer yaklaşımları göz önünde bulundurabilirsiniz. Son olarak, hizmetin sürekli çalışması ve bir Windows Server'da dağıtılması gerekiyorsa bir Windows Hizmeti kullanabilirsiniz.
Ancak uygulama havuzuna dağıtılan bir WebHost
uygulama için bile uygulamanın bellek içi önbelleğini yeniden doldurma veya temizleme gibi senaryolar söz konusu olabilir.
Arabirim, IHostedService
ASP.NET Core web uygulamasında (.NET Core 2.0 ve sonraki sürümlerde) veya herhangi bir işlem/konakta (ile .NET Core 2.1'den IHost
başlayarak) arka plan görevlerini başlatmak için kullanışlı bir yol sağlar. Ana avantajı, konak kapatılırken arka plan görevlerinizin kodunu temizlemek için düzgün bir iptal ile elde ettiğiniz fırsattır.
Ek kaynaklar
ASP.NET Core/Standard 2.0'da zamanlanmış görev oluşturma
https://blog.maartenballiauw.be/post/2017/08/01/building-a-scheduled-cache-updater-in-aspnet-core-2.htmlASP.NET Core 2.0'da IHostedService Uygulama
https://www.stevejgordon.co.uk/asp-net-core-2-ihostedserviceASP.NET Core 2.1 kullanan GenericHost Örneği
https://github.com/aspnet/Hosting/tree/release/2.1/samples/GenericHostSample