Číst v angličtině

Sdílet prostřednictvím


Služby pracovních procesů v .NET

Existuje mnoho důvodů pro vytváření dlouhotrvajících služeb, například:

  • Zpracování dat náročných na procesor
  • Řazení pracovních položek do fronty na pozadí
  • Provádění operace založené na čase podle plánu.

Zpracování služby na pozadí obvykle nezahrnuje uživatelské rozhraní, ale uživatelská rozhraní je možné kolem nich sestavit. V prvních dnech s rozhraním .NET Framework mohou vývojáři windows pro tyto účely vytvářet služby Systému Windows. Nyní s .NET můžete použít BackgroundService, což je implementace IHostedService, nebo implementovat vlastní.

S .NET už nejste omezeni na Windows. Můžete vyvíjet multiplatformní služby na pozadí. Hostované služby jsou připravené pro protokolování, konfiguraci a injektáž závislostí (DI). Jsou součástí sady rozšíření knihoven, což znamená, že jsou zásadní pro všechny úlohy .NET, které pracují s obecným hostitelem.

Důležité

Instalace sady .NET SDK také nainstaluje Microsoft.NET.Sdk.Worker šablonu pracovního procesu. Jinými slovy, po instalaci sady .NET SDK můžete vytvořit nový pracovní proces pomocí příkazu dotnet new worker . Pokud používáte Visual Studio, šablona se skryje, dokud se nenainstaluje volitelná ASP.NET a úloha vývoje webu.

Terminologie

Mnoho termínů se omylem používá jako synonymum. Tato část definuje některé z těchto termínů, aby bylo jejich záměr v tomto článku zjevnější.

  • Služba na pozadí: Typ BackgroundService .
  • Hostovaná služba: Implementace IHostedServicenebo IHostedService samotné.
  • Dlouhotrvající služba: Jakákoli služba, která běží nepřetržitě.
  • Služba Systému Windows: Infrastruktura služeb systému Windows, která byla původně zaměřena na rozhraní .NET Framework, ale nyní je přístupná prostřednictvím .NET.
  • Pracovní služba: Šablona pracovní služby .

Šablona služby pracovního procesu

Šablona pracovní služby je k dispozici v rozhraní .NET CLI a sadě Visual Studio. Další informace najdete v tématu .NET CLI– dotnet new worker šablona. Šablona se skládá z třídy Program a Worker třídy.

using App.WorkerService;

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

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

Předchozí Program třída:

Výchozí hodnoty šablony

Šablona Pracovního procesu ve výchozím nastavení nepovoluje uvolňování paměti serveru( GC), protože existuje mnoho faktorů, které hrají roli při určování jeho potřeby. Všechny scénáře, které vyžadují dlouhotrvající služby, by měly zvážit dopad na výkon tohoto výchozího nastavení. Pokud chcete povolit GC serveru, přidejte ServerGarbageCollection uzel do souboru projektu:

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

Kompromisy a aspekty

Povolený Disabled
Efektivní správa paměti: Automaticky uvolní nevyužitou paměť, aby se zabránilo nevrácené paměti a optimalizovalo využití prostředků. Vylepšený výkon v reálném čase: Zabraňuje potenciálním pozastavením nebo přerušením způsobeným uvolňováním paměti v aplikacích citlivých na latenci.
Dlouhodobá stabilita: Pomáhá udržovat stabilní výkon v dlouhodobých službách tím, že spravuje paměť v delších obdobích. Efektivita prostředků: Může šetřit prostředky procesoru a paměti v prostředích s omezenými prostředky prostředků.
Omezená údržba: Minimalizuje potřebu ruční správy paměti a zjednodušuje údržbu. Ruční řízení paměti: Poskytuje jemně odstupňovanou kontrolu nad pamětí pro specializované aplikace.
Předvídatelné chování: Přispívá k konzistentnímu a předvídatelnému chování aplikace. Vhodné pro krátkodobé procesy: Minimalizuje režii uvolňování paměti pro krátkodobé nebo dočasné procesy.

Další informace týkající se aspektů výkonu naleznete v tématu Server GC. Další informace o konfiguraci serveru GC naleznete v příkladech konfigurace serveru GC.

Worker – třída

WorkerŠablona poskytuje jednoduchou implementaci.

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);
        }
    }
}

Předchozí Worker třída je podtřída BackgroundService, která implementuje IHostedService. Jedná se BackgroundService o abstract class podtřídu a vyžaduje, aby implementovala BackgroundService.ExecuteAsync(CancellationToken)podtřídu . V implementaci ExecuteAsync šablony smyčky jednou za sekundu zaznamenává aktuální datum a čas, dokud se proces nezruší.

Soubor projektu

Šablona pracovního procesu spoléhá na následující soubor Sdkprojektu:

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

Další informace najdete v tématu Sady SDK projektu .NET.

Balíček NuGet

Aplikace založená na šabloně Pracovního procesu používá Microsoft.NET.Sdk.Worker sadu SDK a obsahuje explicitní odkaz na balíček Microsoft.Extensions.Hosting .

Kontejnery a přizpůsobitelnost cloudu

U většiny moderních úloh .NET jsou kontejnery realizovatelnou možností. Při vytváření dlouhotrvající služby ze šablony pracovního procesu v sadě Visual Studio se můžete přihlásit k podpoře Dockeru. Tím se vytvoří soubor Dockerfile , který kontejnerizuje vaši aplikaci .NET. Soubor Dockerfile je sada instrukcí pro sestavení image. V případě aplikací .NET se soubor Dockerfile obvykle nachází v kořenovém adresáři vedle souboru řešení.

# 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"]

Mezi předchozí kroky souboru Dockerfile patří:

  • Nastavení základní image z mcr.microsoft.com/dotnet/runtime:8.0 aliasu base.
  • Změna pracovního adresáře na /app
  • Nastavení aliasu build z obrázku mcr.microsoft.com/dotnet/sdk:8.0
  • Změna pracovního adresáře na /src
  • Kopírování obsahu a publikování aplikace .NET:
  • Přenos image sady .NET SDK z mcr.microsoft.com/dotnet/runtime:8.0 (aliasu base )
  • Kopírování publikovaného výstupu sestavení z /publish
  • Definování vstupního bodu, na který delegáti .dotnet App.BackgroundService.dll

Tip

MCR mcr.microsoft.com je zkratka pro Microsoft Container Registry a je syndikovaný katalog kontejnerů Microsoftu z oficiálního centra Dockeru. Článek o syndikaci katalogu kontejnerů Microsoftu obsahuje další podrobnosti.

Když cílíte na Docker jako strategii nasazení pro službu pracovního procesu .NET, je v souboru projektu potřeba vzít v úvahu několik aspektů:

<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="9.0.0" />
    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />
  </ItemGroup>
</Project>

V předchozím souboru <DockerDefaultTargetOS> projektu prvek určuje Linux jako cíl. Pokud chcete cílit na kontejnery Windows, použijte Windows místo toho. Balíček Microsoft.VisualStudio.Azure.Containers.Tools.Targets NuGet se automaticky přidá jako odkaz na balíček při výběru podpory Dockeru ze šablony.

Další informace o Dockeru s .NET najdete v kurzu : Kontejnerizace aplikace .NET. Další informace o nasazení do Azure najdete v kurzu : Nasazení pracovní služby do Azure.

Důležité

Pokud chcete využít tajné kódy uživatele se šablonou Pracovního procesu, budete muset explicitně odkazovat na Microsoft.Extensions.Configuration.UserSecrets balíček NuGet.

Rozšiřitelnost hostované služby

Rozhraní IHostedService definuje dvě metody:

Tyto dvě metody slouží jako metody životního cyklu – volají se během spouštění a zastavování událostí hostitele.

Poznámka

Při přepsání buď StartAsync nebo StopAsync metod, je nutné volat a await metodu base třídy, aby se zajistilo, že služba spustí nebo vypne správně.

Důležité

Rozhraní slouží jako omezení parametru obecného typu pro metodu AddHostedService<THostedService>(IServiceCollection) rozšíření, což znamená, že jsou povoleny pouze implementace. Můžete bezplatně používat podtřídu BackgroundService nebo implementovat vlastní.

Dokončení signálu

Ve většině běžných scénářů nemusíte explicitně signalizovat dokončení hostované služby. Když hostitel spustí služby, jsou navržené tak, aby běžely, dokud se hostitel nezastaví. V některých scénářích ale možná budete muset po dokončení služby signalizovat dokončení celé hostitelské aplikace. Pokud chcete signalizovat dokončení, zvažte následující Worker třídu:

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();
    }
}

V předchozím kódu metoda neprovádí smyčku ExecuteAsync a po dokončení volání IHostApplicationLifetime.StopApplication().

Důležité

To bude signalizovat hostiteli, že by se měl zastavit, a bez tohoto volání StopApplication hostitele bude nadále běžet neomezeně dlouho.

Další informace naleznete v tématu:

Viz také