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.

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

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.

Diagram comparing ASP.NET Core IWebHost and .NET Core IHost.

Ş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 Hostarası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 IHostedServicesyapı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 WebHostgeniş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 IHostgerekir.

Barındırılan hizmetleri WebHost'unuza veya Konağınıza kaydetme

kullanımı veya içinde oldukça benzer olduğundan arabirimde WebHostHostdaha 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 ILoggeryaygı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 IHostedServicebir arka plan görevine boşaltabilirsiniz.

veya içine HostWebHost 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 IHostedServicekaydettiğ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ı IWebHostBuilderkullanarak 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.

Diagram showing that IWebHost and IHost can host many services.

Ş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 IHostbaş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