Servicios de trabajo en .NET
Hay numerosas razones para crear servicios de ejecución larga, como:
- Procesamiento de datos de uso intensivo de CPU
- Cola de elementos de trabajo en segundo plano
- Realización de una operación basada en el tiempo según una programación
Normalmente, el procesamiento de servicios en segundo plano no implica una interfaz de usuario (UI), pero se pueden crear interfaces de usuario en torno a ellos. En los inicios de .NET Framework, los desarrolladores de Windows podían crear servicios de Windows por estos motivos. Ahora con .NET puede usar BackgroundService, que es una implementación de IHostedService, o implementar el suyo propio.
Con .NET, ya no está limitado a Windows. Puede desarrollar servicios en segundo plano multiplataforma. Los servicios hospedados están listos para el registro, la configuración y la inserción de dependencias (ID). Forman parte del conjunto de extensiones de bibliotecas, lo que significa que son fundamentales para todas las cargas de trabajo de .NET que funcionan con el host genérico.
Terminología
Muchos términos se usan erróneamente como sinónimos. En esta sección, hay definiciones de algunos de estos términos para que su intención sea más evidente.
- Servicio en segundo plano: hace referencia al tipo BackgroundService.
- Servicio hospedado: implementaciones de IHostedService o referencias al propio IHostedService.
- Servicio de ejecución larga: cualquier servicio que se ejecuta continuamente.
- Windows Service: la infraestructura de Windows Service, originalmente basada en .NET Framework, a la que se puede acceder ahora desde .NET.
- Worker Service: hace referencia a la plantilla Worker Service.
Plantilla Worker Service
La plantilla Worker Service está disponible para la CLI de .NET y Visual Studio. Para más información, vea la plantilla dotnet new worker de la CLI de .NET. La plantilla consta de una clase Program y Worker.
using App.WorkerService;
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
})
.Build();
await host.RunAsync();
La clase Program anterior:
- Crea la interfaz IHostBuilder predeterminada.
- Llama a ConfigureServices para agregar la clase
Workercomo un servicio hospedado con AddHostedService. - Compila una interfaz IHost a partir del generador.
- Llama a
Runen la instancia dehost, que ejecuta la aplicación.
El archivo Program.cs de la plantilla se puede reescribir mediante instrucciones de nivel superior:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using App.WorkerService;
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
})
.Build();
await host.RunAsync();
Se trata del equivalente funcional de la plantilla original. Para más información sobre las características de C# 9, vea Novedades de C# 9.0.
En cuanto a Worker, la plantilla proporciona una implementación sencilla.
namespace App.WorkerService
{
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
public Worker(ILogger<Worker> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.Delay(1000, stoppingToken);
}
}
}
}
La clase Worker anterior es una subclase de BackgroundService, que implementa IHostedService. BackgroundService es abstract class y requiere la subclase para implementar BackgroundService.ExecuteAsync(CancellationToken). En la implementación de la plantilla, los bucles de ExecuteAsync se recorren una vez por segundo, registrando la fecha y hora actuales hasta que se señale el proceso para la cancelación.
El archivo del proyecto
La plantilla Worker Service se basa en el siguiente archivo del proyecto Sdk:
<Project Sdk="Microsoft.NET.Sdk.Worker">
Para más información, vea SDK de proyectos de .NET.
Paquete de NuGet
Una aplicación basada en la plantilla Worker Service usa el SDK de Microsoft.NET.Sdk.Worker y tiene una referencia de paquete explícita al paquete Microsoft.Extensions.Hosting.
Contenedores y adopción de la nube
Con las cargas de trabajo de .NET más modernas, los contenedores son una opción viable. Al crear un servicio de ejecución larga a partir de la plantilla Worker Service en Visual Studio, puede optar por la compatibilidad con Docker. Al hacerlo, se creará un Dockerfile que incluirá una aplicación .NET en un contenedor. Un Dockerfile es un conjunto de instrucciones para compilar una imagen. En el caso de las aplicaciones .NET, el Dockerfile normalmente se encuentra en la raíz del directorio junto a un archivo de solución.
# 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:5.0 AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/sdk:5.0 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"]
Los pasos anteriores del Dockerfile incluyen:
- Establecer la imagen base de
mcr.microsoft.com/dotnet/runtime:5.0como el aliasbase. - Cambiar el directorio de trabajo a /app.
- Establecer el alias
buildde la imagenmcr.microsoft.com/dotnet/sdk:5.0. - Cambiar el directorio de trabajo a /src.
- Copiar el contenido y publicar la aplicación .NET:
- La aplicación se publica mediante el comando
dotnet publish.
- La aplicación se publica mediante el comando
- Retransmitir la imagen del SDK de .NET desde
mcr.microsoft.com/dotnet/runtime:5.0(el aliasbase). - Copiar la salida de compilación publicada de /publish.
- Definir el punto de entrada, que delega en
dotnet App.BackgroundService.dll.
Sugerencia
MRC en mcr.microsoft.com significa "Microsoft Container Registry", y es el catálogo de contenedores sindicados de Microsoft del centro de Docker oficial. El artículo Catálogo de contenedores sindicados de Microsoft contiene información adicional.
El establecer Docker como destino de una estrategia de implementación para la plantilla Worker Service de .NET, hay algunas consideraciones en el archivo del proyecto:
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
<RootNamespace>App.WorkerService</RootNamespace>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.11.1" />
</ItemGroup>
</Project>
En el archivo del proyecto anterior, el elemento <DockerDefaultTargetOS> especifica Linux como destino. Para establecer los contenedores de Windows como destino, use Windows en su lugar. El paquete de NuGet Microsoft.VisualStudio.Azure.Containers.Tools.Targets se agrega automáticamente como una referencia de paquete cuando se selecciona la compatibilidad con Docker en la plantilla.
Para más información sobre Docker con .NET, vea Tutorial: Incluir una aplicación de .NET Core en un contenedor. Para más información sobre la implementación en Azure, vea Tutorial: Implementación de una plantilla Worker Service en Azure.
Extensibilidad del servicio hospedado
La interfaz IHostedService define dos métodos:
Estos dos métodos sirven como métodos de ciclo de vida: se invocan durante los eventos de inicio y de detección del host, respectivamente.
Importante
La interfaz actúa como una restricción de parámetro de tipo genérico en el método de extensión AddHostedService<THostedService>(IServiceCollection), lo que significa que solo se permiten implementaciones. Puede usar la clase BackgroundService proporcionada con una subclase, o bien implementar la suya propia por completo.
Vea también
- Tutoriales de la subclase BackgroundService:
- Implementación de la interfaz IHostedService personalizada: