.NET'te çalışan hizmetleri

Uzun süre çalışan hizmetler oluşturmanın çeşitli nedenleri vardır:

  • Yoğun CPU kullanan verileri işleme.
  • Arka planda iş öğelerini kuyruğa alma.
  • Zamanlamaya göre zaman tabanlı bir işlem gerçekleştirme.

Arka plan hizmeti işleme genellikle bir kullanıcı arabirimi (UI) içermez, ancak bunların etrafında URI'ler oluşturulabilir. .NET Framework ile ilk günlerde, Windows geliştiricileri bu amaçlar için Windows Hizmetleri oluşturabilirdi. Artık .NET ile uygulamasını kullanabilir BackgroundServiceveya kendi uygulamanızı IHostedServiceuygulayabilirsiniz.

.NET ile artık Windows ile sınırlı değilsiniz. Platformlar arası arka plan hizmetleri geliştirebilirsiniz. Barındırılan hizmetler günlüğe kaydetmeye, yapılandırmaya ve bağımlılık eklemeye (DI) hazırdır. Bunlar, kitaplıkların uzantı paketinin bir parçasıdır ve genel konakla çalışan tüm .NET iş yükleri için temeldir.

Önemli

.NET SDK'sını yüklemek ve çalışan şablonunu da yükler Microsoft.NET.Sdk.Worker . Başka bir deyişle, .NET SDK'sını yükledikten sonra dotnet new worker komutunu kullanarak yeni bir çalışan oluşturabilirsiniz. Visual Studio kullanıyorsanız, isteğe bağlı ASP.NET ve web geliştirme iş yükü yüklenene kadar şablon gizlenir.

Terminoloji

Birçok terim yanlışlıkla eş anlamlı olarak kullanılır. Bu bölüm, bu makaledeki amaçlarını daha belirgin hale getirmek için bu terimlerden bazılarını tanımlar.

  • Arka Plan Hizmeti: Türü BackgroundService .
  • Barındırılan IHostedServiceHizmet: uygulaması veya IHostedService kendisi.
  • Uzun süre çalışan Hizmet: Sürekli çalışan tüm hizmetler.
  • Windows Hizmeti: Başlangıçta .NET Framework merkezli olan ancak artık .NET üzerinden erişilebilen Windows Hizmeti altyapısı.
  • Çalışan Hizmeti: Çalışan Hizmeti şablonu.

Çalışan Hizmeti şablonu

Çalışan Hizmeti şablonu .NET CLI ve Visual Studio'da kullanılabilir. Daha fazla bilgi için bkz . .NET CLI, dotnet new worker - şablonu. Şablon bir Program ve Worker sınıfından oluşur.

using App.WorkerService;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();

IHost host = builder.Build();
host.Run();

Önceki Program sınıf:

  • oluşturur HostApplicationBuilder.
  • öğesini barındırılan Worker hizmet olarak kaydetmek için çağrılarAddHostedService.
  • Oluşturucudan bir IHost oluşturur.
  • host Uygulamayı çalıştıran örnekte çağrılarRun.

Şablon varsayılanları

Çalışan şablonu varsayılan olarak sunucu çöp toplamayı (GC) etkinleştirmez çünkü gerekliliğini belirlemede rol oynayan çok sayıda faktör vardır. Uzun süre çalışan hizmetler gerektiren tüm senaryolar bu varsayılanın performans üzerindeki etkilerini dikkate almalıdır. Sunucu GC'yi etkinleştirmek için düğümü proje dosyasına ekleyin ServerGarbageCollection :

<PropertyGroup>
    <ServerGarbageCollection>true</ServerGarbageCollection>
</PropertyGroup>

Dengeler ve dikkat edilmesi gerekenler

Etkin Devre Dışı
Verimli bellek yönetimi: Bellek sızıntılarını önlemek ve kaynak kullanımını iyileştirmek için kullanılmayan belleği otomatik olarak geri alır. Geliştirilmiş gerçek zamanlı performans: Gecikme süresine duyarlı uygulamalarda atık toplamanın neden olduğu olası duraklamaları veya kesintileri önler.
Uzun vadeli kararlılık: Uzun süreler boyunca belleği yöneterek uzun süre çalışan hizmetlerde kararlı performansın korunmasına yardımcı olur. Kaynak verimliliği: Kaynak kısıtlanmış ortamlarda CPU ve bellek kaynaklarından tasarruf edebilir.
Daha az bakım: El ile bellek yönetimi gereksinimini en aza indirerek bakımı basitleştirir. El ile bellek denetimi: Özel uygulamalar için bellek üzerinde ayrıntılı denetim sağlar.
Öngörülebilir davranış: Tutarlı ve öngörülebilir uygulama davranışına katkıda bulunur. Kısa süreli işlemler için uygundur: Kısa süreli veya kısa ömürlü işlemler için çöp toplama yükünü en aza indirir.

Performansla ilgili dikkat edilmesi gerekenler hakkında daha fazla bilgi için bkz . Sunucu GC. Sunucu GC'sini yapılandırma hakkında daha fazla bilgi için bkz . Sunucu GC yapılandırma örnekleri.

Çalışan sınıfı

şablonuna Workergelince, şablon basit bir uygulama sağlar.

namespace App.WorkerService;

public sealed class Worker(ILogger<Worker> logger) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            await Task.Delay(1_000, stoppingToken);
        }
    }
}

Yukarıdaki Worker sınıf, uygulamasını uygulayan bir alt sınıfıdırBackgroundServiceIHostedService. BackgroundService, ve abstract class alt sınıfının uygulamasını BackgroundService.ExecuteAsync(CancellationToken)gerektirir. Şablon uygulamasında, ExecuteAsync işlem iptal etmek için işaretlenene kadar geçerli tarih ve saati günlüğe kaydetmek için saniyede bir döngü yapılır.

Proje dosyası

Çalışan şablonu aşağıdaki proje dosyasına Sdkdayanır:

<Project Sdk="Microsoft.NET.Sdk.Worker">

Daha fazla bilgi için bkz . .NET proje SDK'ları.

NuGet paketi

Çalışan şablonunu temel alan bir uygulama SDK'yi Microsoft.NET.Sdk.Worker kullanır ve Microsoft.Extensions.Hosting paketine açık bir paket başvurusuna sahiptir.

Kapsayıcılar ve buluta uyarlanabilirlik

Çoğu modern .NET iş yükünde kapsayıcılar uygulanabilir bir seçenektir. Visual Studio'da Çalışan şablonundan uzun süre çalışan bir hizmet oluştururken Docker desteğini kabul edebilirsiniz. Bunu yaptığınızda .NET uygulamanızı kapsayıcılı hale getiren bir Dockerfile oluşturulur. Dockerfile, görüntü oluşturmaya yönelik yönergeler kümesidir. .NET uygulamaları için Dockerfile genellikle bir çözüm dosyasının yanındaki dizinin kökünde yer alır.

# See https://aka.ms/containerfastmode to understand how Visual Studio uses this
# Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/runtime:8.0@sha256:e6b552fd7a0302e4db30661b16537f7efcdc0b67790a47dbf67a5e798582d3a5 AS base
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:8.0@sha256:35792ea4ad1db051981f62b313f1be3b46b1f45cadbaa3c288cd0d3056eefb83 AS build
WORKDIR /src
COPY ["background-service/App.WorkerService.csproj", "background-service/"]
RUN dotnet restore "background-service/App.WorkerService.csproj"
COPY . .
WORKDIR "/src/background-service"
RUN dotnet build "App.WorkerService.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "App.WorkerService.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "App.WorkerService.dll"]

Yukarıdaki Dockerfile adımları şunlardır:

  • temel görüntüsünü mcr.microsoft.com/dotnet/runtime:8.0 diğer ad baseolarak ayarlama.
  • Çalışma dizini /app olarak değiştiriliyor.
  • Görüntüden build mcr.microsoft.com/dotnet/sdk:8.0 diğer adı ayarlama.
  • Çalışma dizini /src olarak değiştiriliyor.
  • İçeriği kopyalama ve .NET uygulamasını yayımlama:
  • .NET SDK görüntüsünün mcr.microsoft.com/dotnet/runtime:8.0 geçişini ( base diğer ad) gerçekleştirme.
  • Yayımlanan derleme çıktısı /publish'dan kopyalanıyor.
  • öğesini temsil dotnet App.BackgroundService.dlleden giriş noktasını tanımlama.

İpucu

içindeki mcr.microsoft.com MCR, "Microsoft Container Registry" anlamına gelir ve Microsoft'un resmi Docker hub'ından gelen genel kapsayıcı kataloğudur. Microsoft syndicates kapsayıcı kataloğu makalesi ek ayrıntılar içerir.

Docker'ı .NET Çalışan Hizmetiniz için dağıtım stratejisi olarak hedeflediğinizde, proje dosyasında dikkat edilmesi gereken birkaç nokta vardır:

<Project Sdk="Microsoft.NET.Sdk.Worker">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>true</ImplicitUsings>
    <RootNamespace>App.WorkerService</RootNamespace>
    <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />
  </ItemGroup>
</Project>

Yukarıdaki proje dosyasında öğesi <DockerDefaultTargetOS> hedefi olarak belirtir Linux . Windows kapsayıcılarını hedeflemek için bunun yerine kullanın Windows . Microsoft.VisualStudio.Azure.Containers.Tools.Targets Şablondan Docker desteği seçildiğinde NuGet paketi otomatik olarak paket başvurusu olarak eklenir.

.NET ile Docker hakkında daha fazla bilgi için bkz . Öğretici: .NET uygulamasını kapsayıcıya alma. Azure'a dağıtma hakkında daha fazla bilgi için bkz . Öğretici: Azure'a Çalışan Hizmeti Dağıtma.

Önemli

Çalışan şablonuyla Kullanıcı Gizli Dizileri'ni kullanmak istiyorsanız NuGet paketine Microsoft.Extensions.Configuration.UserSecrets açıkça başvurmanız gerekir.

Barındırılan Hizmet genişletilebilirliği

IHostedService Arabirimi iki yöntem tanımlar:

Bu iki yöntem yaşam döngüsü yöntemi görevi görür. Bunlar sırasıyla konak başlatma ve durdurma olayları sırasında çağrılır.

Not

veya StopAsync yöntemlerini geçersiz kıldığınızdaStartAsync, hizmetin düzgün şekilde başlatıldığından base ve/veya kapandığından emin olmak için ve await sınıf yöntemini çağırmalısınız.

Önemli

Arabirim, uzantı yönteminde AddHostedService<THostedService>(IServiceCollection) genel tür parametre kısıtlaması görevi görür, yani yalnızca uygulamalara izin verilir. Sağlanan BackgroundService öğesini bir alt sınıfla kullanabilir veya tamamen kendi sınıfınızı uygulayabilirsiniz.

Sinyal tamamlama

Çoğu yaygın senaryoda, barındırılan bir hizmetin tamamlanmasını açıkça işaret etmeniz gerekmez. Konak hizmetleri başlattığında, konak durdurulana kadar çalışacak şekilde tasarlanmıştır. Ancak bazı senaryolarda, hizmet tamamlandığında konak uygulamasının tamamının tamamlanmasının sinyalini vermeniz gerekebilir. Tamamlanma sinyali vermek için aşağıdaki Worker sınıfı göz önünde bulundurun:

namespace App.SignalCompletionService;

public sealed class Worker(
    IHostApplicationLifetime hostApplicationLifetime,
    ILogger<Worker> logger) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // TODO: implement single execution logic here.
        logger.LogInformation(
            "Worker running at: {Time}", DateTimeOffset.Now);

        await Task.Delay(1_000, stoppingToken);

        // When completed, the entire app host will stop.
        hostApplicationLifetime.StopApplication();
    }
}

Önceki kodda ExecuteAsync yöntemi döngü yapmaz ve tamamlandığında öğesini çağırır IHostApplicationLifetime.StopApplication().

Önemli

Bu, konağa durması gerektiğini bildirir ve bu çağrı olmadan konağa StopApplication süresiz olarak çalışmaya devam eder.

Daha fazla bilgi için bkz.

Ayrıca bkz.