Existem inúmeras razões para a criação de serviços de longa duração, tais como:
Processamento de dados com uso intensivo de CPU.
Enfileiramento de itens de trabalho em segundo plano.
Executar uma operação baseada no tempo em um cronograma.
O processamento de serviço em segundo plano geralmente não envolve uma interface do usuário (UI), mas as interfaces do usuário podem ser criadas em torno delas. Nos primórdios do .NET Framework, os desenvolvedores do Windows podiam criar os Serviços do Windows para esses fins. Agora, com o .NET, você pode usar o , que é uma implementação do IHostedService, ou implementar o BackgroundServiceseu próprio.
Com o .NET, você não está mais restrito ao Windows. Você pode desenvolver serviços em segundo plano entre plataformas. Os serviços hospedados estão prontos para registro, configuração e injeção de dependência (DI). Eles fazem parte do conjunto de extensões de bibliotecas, o que significa que são fundamentais para todas as cargas de trabalho do .NET que funcionam com o host genérico.
Importante
A instalação do SDK do .NET também instala o Microsoft.NET.Sdk.Worker modelo e o de trabalho. Em outras palavras, depois de instalar o SDK do .NET, você pode criar um novo trabalhador usando o comando dotnet new worker . Se você estiver usando o Visual Studio, o modelo ficará oculto até que a carga de trabalho opcional de ASP.NET e desenvolvimento da Web seja instalada.
Terminologia
Muitos termos são erroneamente usados como sinônimos. Esta seção define alguns desses termos para tornar sua intenção neste artigo mais aparente.
Serviço de longa duração: qualquer serviço executado continuamente.
Serviço Windows: A infraestrutura de Serviço do Windows, originalmente centrada no .NET Framework, mas agora acessível via .NET.
Serviço do Trabalhador: O modelo do Serviço do Trabalhador.
Modelo de Serviço do Trabalhador
O modelo Worker Service está disponível na CLI do .NET e no Visual Studio. Para obter mais informações, consulte .NET CLI, dotnet new worker - template. O modelo consiste em uma Program classe e Worker .
Chama Run a host instância, que executa o aplicativo.
Padrões de modelo
O modelo Worker não habilita a coleta de lixo do servidor (GC) por padrão, pois há vários fatores que desempenham um papel na determinação de sua necessidade. Todos os cenários que exigem serviços de longa execução devem considerar as implicações de desempenho desse padrão. Para habilitar o GC do servidor, adicione o ServerGarbageCollection nó ao arquivo de projeto:
Gerenciamento eficiente de memória: recupera automaticamente a memória não utilizada para evitar vazamentos de memória e otimizar o uso de recursos.
Melhor desempenho em tempo real: evita possíveis pausas ou interrupções causadas pela coleta de lixo em aplicativos sensíveis à latência.
Estabilidade a longo prazo: Ajuda a manter um desempenho estável em serviços de longa duração, gerenciando a memória por longos períodos.
Eficiência de recursos: pode conservar recursos de CPU e memória em ambientes com recursos limitados.
Manutenção reduzida: Minimiza a necessidade de gerenciamento manual de memória, simplificando a manutenção.
Controle manual de memória: Fornece controle refinado sobre a memória para aplicações especializadas.
Comportamento previsível: contribui para um comportamento consistente e previsível do aplicativo.
Adequado para processos de curta duração: Minimiza a sobrecarga da coleta de lixo para processos efêmeros ou de curta duração.
Para obter mais informações sobre considerações de desempenho, consulte GC do servidor. Para obter mais informações sobre como configurar o GC do servidor, consulte Exemplos de configuração do GC do servidor.
Classe operária
Quanto ao Worker, o modelo fornece uma implementação simples.
Com a maioria das cargas de trabalho .NET modernas, os contêineres são uma opção viável. Ao criar um serviço de longa execução a partir do modelo Worker no Visual Studio, você pode optar pelo suporte ao Docker. Isso cria um Dockerfile que conteineriza seu aplicativo .NET. Um Dockerfile é um conjunto de instruções para criar uma imagem. Para aplicativos .NET, o Dockerfile geralmente fica na raiz do diretório ao lado de um arquivo de solução.
# 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"]
As etapas anteriores do Dockerfile incluem:
Definindo a imagem base como mcr.microsoft.com/dotnet/runtime:8.0 o alias base.
Alterando o diretório de trabalho para /app.
Definindo o build alias da mcr.microsoft.com/dotnet/sdk:8.0 imagem.
Alterando o diretório de trabalho para /src.
Copiando o conteúdo e publicando o aplicativo .NET:
O aplicativo é publicado usando o dotnet publish comando.
Retransmissão da imagem do SDK do .NET a partir de mcr.microsoft.com/dotnet/runtime:8.0 (o base alias).
Copiando a saída de compilação publicada do /publish.
O MCR em mcr.microsoft.com significa "Microsoft Container Registry", e é o catálogo de contêineres sindicados da Microsoft a partir do hub oficial do Docker. O artigo do catálogo de contêineres de sindicatos da Microsoft contém detalhes adicionais.
Quando você direciona o Docker como uma estratégia de implantação para seu .NET Worker Service, há algumas considerações no arquivo de projeto:
No arquivo de projeto anterior, o <DockerDefaultTargetOS> elemento especifica Linux como seu destino. Para direcionar contêineres do Windows, use Windows em vez disso. O Microsoft.VisualStudio.Azure.Containers.Tools.Targets pacote NuGet é adicionado automaticamente como uma referência de pacote quando o suporte ao Docker é selecionado no modelo.
Se quiser aproveitar os Segredos de Usuário com o modelo de Trabalhador, será necessário fazer referência explícita ao Microsoft.Extensions.Configuration.UserSecrets pacote NuGet.
Esses dois métodos servem como métodos de ciclo de vida - eles são chamados durante os eventos de início e parada do host, respectivamente.
Nota
Ao substituir um ou StartAsyncStopAsync métodos, você deve chamar e await o base método de classe para garantir que o serviço seja iniciado e/ou desligado corretamente.
Importante
A interface serve como uma restrição de parâmetro de tipo genérico no método de extensão, o AddHostedService<THostedService>(IServiceCollection) que significa que apenas implementações são permitidas. Você é livre para usar o fornecido BackgroundService com uma subclasse, ou implementar o seu próprio completamente.
Conclusão do sinal
Na maioria dos cenários comuns, você não precisa sinalizar explicitamente a conclusão de um serviço hospedado. Quando o host inicia os serviços, eles são projetados para serem executados até que o host seja interrompido. Em alguns cenários, no entanto, talvez seja necessário sinalizar a conclusão de todo o aplicativo host quando o serviço for concluído. Para sinalizar a conclusão, considere a seguinte Worker classe:
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();
}
}
A origem deste conteúdo pode ser encontrada no GitHub, onde também pode criar e rever problemas e pedidos Pull. Para mais informações, consulte o nosso guia do contribuidor.
Comentários do .NET
O .NET é um projeto código aberto. Selecione um link para fornecer comentários:
Entenda e implemente a injeção de dependência em um aplicativo ASP.NET Core. Use o contêiner de serviço interno do ASP.NET Core para gerenciar dependências. Registre serviços com o contêiner de serviço.