Werkrolservices in .NET
Er zijn talloze redenen voor het maken van langlopende services, zoals:
- Cpu-intensieve gegevens verwerken.
- Werkitems in de wachtrij plaatsen op de achtergrond.
- Een tijdgebaseerde bewerking uitvoeren op basis van een schema.
Verwerking van achtergrondservices omvat meestal geen gebruikersinterface (UI), maar UIs kunnen er omheen worden gebouwd. In de vroege dagen met .NET Framework konden Windows-ontwikkelaars Windows Services maken voor deze doeleinden. Met .NET kunt u nu de BackgroundService, een implementatie van IHostedServiceof uw eigen implementatie gebruiken.
Met .NET bent u niet langer beperkt tot Windows. U kunt platformoverschrijdende achtergrondservices ontwikkelen. Gehoste services zijn gereed voor logboekregistratie, configuratie en afhankelijkheidsinjectie (DI). Ze maken deel uit van de uitbreidingssuite met bibliotheken, wat betekent dat ze fundamenteel zijn voor alle .NET-workloads die met de algemene host werken.
Belangrijk
Als u de .NET SDK installeert, worden ook de Microsoft.NET.Sdk.Worker
en de werkrolsjabloon geïnstalleerd. Met andere woorden, nadat u de .NET SDK hebt geïnstalleerd, kunt u een nieuwe werkrol maken met behulp van de opdracht nieuwe werkrol dotnet. Als u Visual Studio gebruikt, wordt de sjabloon verborgen totdat de optionele workload voor ASP.NET en webontwikkeling is geïnstalleerd.
Terminologie
Veel termen worden per ongeluk gebruikt. In deze sectie worden enkele van deze termen gedefinieerd om hun intentie in dit artikel duidelijker te maken.
- Background Service: het BackgroundService type.
- Gehoste service: implementaties van IHostedService, of de IHostedService zelf.
- Langlopende service: elke service die continu wordt uitgevoerd.
- Windows-service: de Windows Service-infrastructuur , oorspronkelijk .NET Framework-gericht, maar nu toegankelijk via .NET.
- Worker-service: de sjabloon Worker Service .
Worker Service-sjabloon
De Worker Service-sjabloon is beschikbaar in de .NET CLI en Visual Studio. Zie .NET CLI, dotnet new worker
-sjabloon voor meer informatie. De sjabloon bestaat uit een Program
en Worker
klasse.
using App.WorkerService;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();
IHost host = builder.Build();
host.Run();
De voorgaande Program
klasse:
- Hiermee maakt u een HostApplicationBuilder.
- Roept AddHostedService aan om de
Worker
als een gehoste service te registreren. - Bouwt een IHost van de opbouwfunctie.
- Roept
Run
hethost
exemplaar aan, waarmee de app wordt uitgevoerd.
Standaardinstellingen voor sjablonen
De werkrolsjabloon schakelt standaard de garbagecollection (GC) van de server niet in, omdat er talloze factoren zijn die een rol spelen bij het bepalen van de noodzaak ervan. Alle scenario's waarvoor langlopende services zijn vereist, moeten rekening houden met de gevolgen voor de prestaties van deze standaardinstelling. Als u server-GC wilt inschakelen, voegt u het ServerGarbageCollection
knooppunt toe aan het projectbestand:
<PropertyGroup>
<ServerGarbageCollection>true</ServerGarbageCollection>
</PropertyGroup>
Compromissen en overwegingen
Ingeschakeld | Uitgeschakeld |
---|---|
Efficiënt geheugenbeheer: maakt ongebruikt geheugen automatisch vrij om geheugenlekken te voorkomen en resourcegebruik te optimaliseren. | Verbeterde realtime prestaties: vermijdt mogelijke onderbrekingen of onderbrekingen die worden veroorzaakt door garbagecollection in latentiegevoelige toepassingen. |
Langetermijnstabiliteit: helpt stabiele prestaties in langlopende services te behouden door het geheugen gedurende langere perioden te beheren. | Resource-efficiëntie: kan CPU- en geheugenresources besparen in omgevingen met beperkte resources. |
Verminderd onderhoud: minimaliseert de noodzaak van handmatig geheugenbeheer, waardoor onderhoud wordt vereenvoudigd. | Handmatig geheugenbeheer: biedt nauwkeurige controle over het geheugen voor gespecialiseerde toepassingen. |
Voorspelbaar gedrag: draagt bij aan consistent en voorspelbaar toepassingsgedrag. | Geschikt voor kortdurende processen: minimaliseert de overhead van garbagecollection voor kortstondige of kortstondige processen. |
Zie Server GC voor meer informatie over prestatieoverwegingen. Zie Voorbeelden van server GC-configuratie voor meer informatie over het configureren van server-GC.
Werkrolklasse
Wat de Worker
sjabloon betreft, biedt de sjabloon een eenvoudige implementatie.
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);
}
}
}
De voorgaande Worker
klasse is een subklasse van BackgroundService, die implementeert IHostedService. Dit BackgroundService is een abstract class
en vereist dat de subklasse wordt geïmplementeerd BackgroundService.ExecuteAsync(CancellationToken). In de sjabloon-implementatie worden de ExecuteAsync
lussen eenmaal per seconde geregistreerd, waarbij de huidige datum en tijd worden geregistreerd totdat het proces wordt gesignaleerd om te annuleren.
Het projectbestand
De worker-sjabloon is afhankelijk van het volgende projectbestand Sdk
:
<Project Sdk="Microsoft.NET.Sdk.Worker">
Zie .NET-project-SDK's voor meer informatie.
NuGet-pakket
Een app op basis van de Worker-sjabloon maakt gebruik van de Microsoft.NET.Sdk.Worker
SDK en heeft een expliciete pakketverwijzing naar het Pakket Microsoft.Extensions.Hosting .
Containers en cloudaanpassing
Bij de meeste moderne .NET-workloads zijn containers een haalbare optie. Wanneer u een langlopende service maakt vanuit de Worker-sjabloon in Visual Studio, kunt u zich aanmelden voor Docker-ondersteuning. Hiermee maakt u een Dockerfile waarmee uw .NET-app in een container wordt geplaatst. Een Dockerfile is een set instructies voor het bouwen van een installatiekopieën. Voor .NET-apps bevindt het Dockerfile zich meestal in de hoofdmap van de map naast een oplossingsbestand.
# 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"]
De voorgaande Dockerfile-stappen omvatten:
- De basisinstallatiekopieën
mcr.microsoft.com/dotnet/runtime:8.0
instellen als de aliasbase
. - De werkmap wijzigen in /app.
build
De alias van demcr.microsoft.com/dotnet/sdk:8.0
afbeelding instellen.- De werkmap wijzigen in /src.
- De inhoud kopiëren en de .NET-app publiceren:
- De app wordt gepubliceerd met behulp van de
dotnet publish
opdracht.
- De app wordt gepubliceerd met behulp van de
- De .NET SDK-installatiekopieën van
mcr.microsoft.com/dotnet/runtime:8.0
(debase
alias) doorsturen. - De gepubliceerde build-uitvoer van de /publish kopiëren.
- Het beginpunt definiëren, waarnaar wordt
dotnet App.BackgroundService.dll
gedelegeerd.
Tip
De MCR in mcr.microsoft.com
staat voor 'Microsoft Container Registry' en is de gesyndiceerde containercatalogus van Microsoft van de officiële Docker-hub. Het artikel over de containercatalogus van Microsoft syndicaten bevat aanvullende informatie.
Wanneer u Docker als implementatiestrategie voor uw .NET Worker-service richt, zijn er enkele overwegingen in het projectbestand:
<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>
In het voorgaande projectbestand geeft Linux
het <DockerDefaultTargetOS>
element het doel op. Als u windows-containers wilt gebruiken, gebruikt Windows
u in plaats daarvan. Het Microsoft.VisualStudio.Azure.Containers.Tools.Targets
NuGet-pakket wordt automatisch toegevoegd als pakketreferentie wanneer Docker-ondersteuning is geselecteerd in de sjabloon.
Zie Zelfstudie: Een .NET-app in een container opslaan voor meer informatie over Docker met .NET. Zie zelfstudie: Een werkrolservice implementeren in Azure voor meer informatie over het implementeren in Azure.
Belangrijk
Als u gebruikersgeheimen wilt gebruiken met de werkrolsjabloon, moet u expliciet verwijzen naar het Microsoft.Extensions.Configuration.UserSecrets
NuGet-pakket.
Uitbreidbaarheid van gehoste services
De IHostedService interface definieert twee methoden:
Deze twee methoden fungeren als levenscyclusmethoden : ze worden respectievelijk aangeroepen tijdens het starten en stoppen van de host.
Notitie
Wanneer u een StartAsync of StopAsync meer methoden overschrijft, moet u aanroepen en await
de base
klassemethode om ervoor te zorgen dat de service wordt gestart en/of correct wordt afgesloten.
Belangrijk
De interface fungeert als een algemene parameterbeperking voor de AddHostedService<THostedService>(IServiceCollection) extensiemethode, wat betekent dat alleen implementaties zijn toegestaan. U kunt de meegeleverde BackgroundService subklasse gebruiken of uw eigen subklasse implementeren.
Signaalvoltooiing
In de meest voorkomende scenario's hoeft u niet expliciet de voltooiing van een gehoste service aan te geven. Wanneer de host de services start, zijn ze ontworpen om te worden uitgevoerd totdat de host is gestopt. In sommige scenario's moet u echter mogelijk aangeven dat de volledige hosttoepassing is voltooid wanneer de service is voltooid. Houd rekening met de volgende Worker
klasse om de voltooiing aan te geven:
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();
}
}
In de voorgaande code wordt de ExecuteAsync
methode niet lus uitgevoerd en wanneer deze is voltooid, wordt deze aangeroepen IHostApplicationLifetime.StopApplication().
Belangrijk
Dit geeft aan dat de host moet worden gestopt en zonder deze aanroep naar StopApplication
de host voor onbepaalde tijd wordt uitgevoerd.
Zie voor meer informatie:
- .NET Generic Host: IHostApplicationLifetime
- .NET Generic Host: Host afsluiten
- .NET Generic Host: afsluiten proces hosten
Zie ook
- BackgroundService zelfstudies voor subklassen:
- Aangepaste IHostedService implementatie: