Services Worker dans .NET
Il existe de nombreuses raisons de créer des services de longue durée, tels que :
- Le traitement de données gourmandes en ressources processeur.
- La mise en file d’attente des éléments de travail en arrière-plan.
- L’exécution d’une opération basée sur le temps selon une planification.
Le traitement du service en arrière-plan n’implique généralement pas d’interface utilisateur, mais les interfaces utilisateur peuvent être créées autour de celles-ci. Dans les premiers jours de .NET Framework, les développeurs Windows pouvaient créer des services Windows à ces fins. Maintenant, avec .NET, vous pouvez utiliser BackgroundService, qui est une implémentation de IHostedService, ou implémenter le vôtre.
Avec .NET, vous n’êtes plus limité à Windows. Vous pouvez développer des services en arrière-plan multiplateforme. Les services hébergés sont prêts pour la journalisation, la configuration et l’injection de dépendances. Ils font partie de la suite d’extensions de bibliothèques, ce qui signifie qu’ils sont fondamentaux pour toutes les charges de travail .NET qui fonctionnent avec l’hôte générique.
Important
L’installation du Kit de développement logiciel (SDK) .NET installe également Microsoft.NET.Sdk.Worker
et le modèle Worker. En d’autres termes, après avoir installé le Kit de développement logiciel (SDK) .NET, vous pouvez créer un Worker à l’aide de la commande dotnet new worker. Si vous utilisez Visual Studio, le modèle est masqué jusqu’à ce que la charge de travail de développement web et l’ASP.NET facultatives soient installées.
Terminologie
De nombreux termes sont utilisés par erreur synonymes. Cette section définit certaines de ces expressions afin de rendre leur intention plus évidente dans cet article.
- Service d’arrière-plan : le type BackgroundService.
- Service hébergé : implémentations du IHostedService ou le IHostedService lui-même.
- Service de longue durée : tout service qui s’exécute en continu.
- Service Windows : l’infrastructure de service Windows centrée à l’origine sur .NET Framework, mais désormais accessible par .NET.
- Service Worker : le modèle de service Worker.
Modèle Service Worker
Le modèle de service Worker est disponible pour la CLI .NET et pour Visual Studio. Pour plus d’informations, consultez CLI .NET, dotnet new worker
: modèle. Le modèle se compose d’une classe Program
et Worker
.
using App.WorkerService;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();
IHost host = builder.Build();
host.Run();
La classe Program
précédente :
- Crée un HostApplicationBuilder.
- Appelle AddHostedService pour inscrire le
Worker
en tant que service hébergé. - Génère un IHost à partir du générateur.
- Appelle
Run
sur l’instancehost
, qui exécute l’application.
Modèles par défaut
Le modèle Worker n’active pas le garbage collection (nettoyage de la mémoire) de serveurs par défaut, car il de nombreux facteurs jouent un rôle dans la détermination de sa nécessité. Tous les scénarios nécessitant des services de longue durée doivent prendre en compte les implications en termes de performances de cette valeur par défaut. Pour activer le nettoyage de la mémoire du serveur, ajoutez le nœud ServerGarbageCollection
au fichier projet :
<PropertyGroup>
<ServerGarbageCollection>true</ServerGarbageCollection>
</PropertyGroup>
Compromis et considérations
Activé(e) | Disabled |
---|---|
Gestion efficace de la mémoire : récupère automatiquement la mémoire inutilisée pour éviter les fuites de mémoire et optimiser l’utilisation des ressources. | Amélioration des performances en temps réel : évite les pauses ou interruptions potentielles causées par le garbage collection dans les applications sensibles à la latence. |
Stabilité à long terme : permet de maintenir des performances stables dans les services à long terme en gérant la mémoire sur des périodes prolongées. | Efficacité des ressources : peut conserver les ressources processeur et mémoire dans des environnements limités aux ressources. |
Maintenance réduite : réduit le besoin de gestion manuelle de la mémoire, ce qui simplifie la maintenance. | Contrôle de mémoire manuel : fournit un contrôle précis de la mémoire pour les applications spécialisées. |
Comportement prévisible : contribue au comportement cohérent et prévisible de l’application. | Adapté aux processus de courte durée : réduit la surcharge du garbage collection pour les processus de courte durée ou éphémères. |
Pour plus d’informations sur les considérations relatives aux performances, consultez Nettoyage de la mémoire du serveur. Pour plus d’informations sur la configuration du nettoyage de la mémoire du serveur, consultez les exemples de Configuration de nettoyage de la mémoire du serveur.
Classe Worker
Quant à Worker
, le modèle fournit une implémentation simple.
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);
}
}
}
La classe Worker
précédente est une sous-classe de BackgroundService, qui implémente IHostedService. BackgroundService est un abstract class
et nécessite que la sous-classe implémente BackgroundService.ExecuteAsync(CancellationToken). Dans l’implémentation du modèle, ExecuteAsync
effectue une boucle une fois par seconde, journalise la date et l’heure jusqu’à ce que le processus soit signalé à annuler.
Fichier projet
Le modèle Worker dépend du fichier projet Sdk
suivant :
<Project Sdk="Microsoft.NET.Sdk.Worker">
Pour plus d’informations, consultez Kits SDK de projet .NET.
Package NuGet
Une application basée sur le modèle Worker utilise le SDK Microsoft.NET.Sdk.Worker
et a une référence de package explicite au package Microsoft.Extensions.Hosting.
Conteneurs et adaptabilité du cloud
Avec la plupart des charges de travail .NET modernes, les conteneurs sont une option viable. Quand vous créez un service de longue durée à partir du modèle Worker dans Visual Studio, vous pouvez choisir la prise en charge de Docker. Cela crée un fichier Dockerfile qui conteneurise votre application .NET. Un Dockerfile est un ensemble d’instructions pour générer une image. Pour les applications .NET, le fichier Dockerfile se trouve généralement à la racine du répertoire à côté d’un fichier de solution.
# 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"]
Les étapes Dockerfile précédentes sont les suivantes :
- La définition de l’image de base à partir de
mcr.microsoft.com/dotnet/runtime:8.0
comme aliasbase
. - La modification du répertoire de travail en /app.
- La définition de l’alias
build
à partir de l’imagemcr.microsoft.com/dotnet/sdk:8.0
. - La modification du répertoire de travail sur /src.
- La copie des contenus et la publication de l’application .NET :
- L’application est publiée à l’aide de la commande
dotnet publish
.
- L’application est publiée à l’aide de la commande
- Le relai de l’image du Kit de développement logiciel (SDK) .NET à partir de
mcr.microsoft.com/dotnet/runtime:8.0
(l’aliasbase
). - La copie de la sortie de build publiée à partir de /publish.
- La définition du point d’entrée, qui délègue à
dotnet App.BackgroundService.dll
.
Conseil
Le MCR dans mcr.microsoft.com
signifie « Microsoft Container Registry » et est le catalogue de conteneurs syndiqué de Microsoft à partir du hub Docker officiel. L’article du Catalogue de conteneurs syndiqué Microsoft contient des détails supplémentaires.
Lorsque vous ciblez Docker en tant que stratégie de déploiement pour votre service Worker .NET, voici quelques points à prendre en compte dans le fichier projet :
<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>
Dans le fichier projet précédent, l’élément <DockerDefaultTargetOS>
spécifie Linux
comme cible. Pour cibler des conteneurs Windows, utilisez Windows
. Le package NuGet Microsoft.VisualStudio.Azure.Containers.Tools.Targets
est automatiquement ajouté en tant que référence de package lorsque la prise en charge de Docker est sélectionnée à partir du modèle.
Pour plus d’informations sur Docker avec .NET, consultez Tutoriel : Conteneuriser une application .NET. Pour plus d’informations sur le déploiement sur Azure, consultez Tutoriel : Déployer un service Worker sur Azure.
Important
Si vous souhaitez tirer parti des Secrets utilisateur avec le modèle Worker, vous devez référencer explicitement le package NuGet Microsoft.Extensions.Configuration.UserSecrets
.
Extensibilité du service hébergé
L'interface IHostedService définit deux méthodes :
Ces deux méthodes servent de méthodes de cycle de vie : elles sont appelées respectivement lors du démarrage de l’hôte et de l’arrêt des événements.
Notes
En cas de substitution de méthodes StartAsync ou StopAsync, vous devez appeler et await
la méthode de classe base
pour vous assurer que le service démarre et/ou s’arrête correctement.
Important
L’interface sert de contrainte de paramètre de type générique sur la méthode d’extension AddHostedService<THostedService>(IServiceCollection), ce qui signifie que seules les implémentations sont autorisées. Vous êtes libre d’utiliser le BackgroundService fourni avec une sous-classe ou d’implémenter entièrement le vôtre.
Complétion du signal
Dans les scénarios les plus courants, vous n’avez pas besoin de signaler explicitement l’achèvement d’un service hébergé. Lorsque l’hôte démarre les services, ils sont conçus pour s’exécuter jusqu’à ce que l’hôte soit arrêté. Dans certains scénarios, toutefois, vous devrez peut-être signaler l’achèvement de l’ensemble de l’application hôte une fois le service terminé. Pour signaler l’achèvement, tenez compte de la classe Worker
suivante :
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();
}
}
Dans le code précédent, la méthode ExecuteAsync
n’effectue pas de boucle, et quand elle est terminée, elle appelle IHostApplicationLifetime.StopApplication().
Important
Cela signale à l’hôte qu’il doit s’arrêter, et sans cet appel à StopApplication
, l’hôte continuera à s’exécuter indéfiniment.
Pour plus d'informations, consultez les pages suivantes :
- Hôte générique .NET : IHostApplicationLifetime
- Hôte générique .NET : arrêt de l’hôte
- Hôte générique .NET : processus d’arrêt d’hébergement
Voir aussi
- BackgroundService Tutoriels de sous-classe :
- Implémentation personnaliséeIHostedService :