Com a evolução do .NET moderno (a partir do .NET Core 3.1 e especialmente no .NET 6+), os Worker Services se tornaram uma forma poderosa e nativa de criar serviços de longa execução, tarefas agendadas, processamento assíncrono e integrações com filas, brokers e jobs — tudo com a performance e a robustez do .NET.
Este artigo cobre:
- 🔍 O que é um Worker Service
- 🧱 Estrutura básica
- 🛠️ Exemplos práticos (fila, cron, background tasks)
- 🧭 Padrões arquiteturais recomendados
- ✅ Boas práticas
🔍 O que é um Worker Service?
Um Worker Service é uma aplicação .NET baseada em IHostedService
, executada em background, ideal para:
- Processamento assíncrono (filas, brokers, eventos)
- Envio de e-mails e notificações
- Tarefas agendadas (cron jobs)
- Monitoração e scraping
- Orquestração de jobs
- Serviços para rodar no Windows/Linux (como daemons)
Ele pode ser implantado em ambientes on-premise, Docker, Kubernetes, Azure App Services, Azure Container Instances, AWS Fargate, entre outros.
🧱 Estrutura de um Worker Service com .NET
Você pode criar um Worker com:
dotnet new worker -n MeuWorkerApp
A estrutura base terá:
MeuWorkerApp/
├── Program.cs
├── Worker.cs
├── appsettings.json
🧪 Exemplo simples
// Worker.cs
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("Executando Worker em: {time}", DateTimeOffset.Now);
await Task.Delay(10000, stoppingToken);
}
}
}
// Program.cs (a partir do .NET 6)
using MeuWorkerApp;
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
})
.Build();
await host.RunAsync();
🛠️ Exemplos práticos
📦 1. Consumindo uma fila (ex: RabbitMQ)
public class QueueWorker : BackgroundService
{
private readonly IRabbitService _rabbit;
public QueueWorker(IRabbitService rabbit)
{
_rabbit = rabbit;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_rabbit.Consume("fila-pagamentos", async (msg) =>
{
// Processa a mensagem
await ProcessarPagamento(msg);
});
}
}
⏰ 2. Job agendado com cron (ex: Hangfire, Quartz)
public class AgendadorWorker : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
if (DateTime.Now.Minute == 0) // Executa de hora em hora
{
await ExecutarJob();
}
await Task.Delay(60000, stoppingToken); // Espera 1 minuto
}
}
}
Para algo mais robusto, use
Quartz.NET
ouHangfire
para agendamentos reais.
📤 3. Envio de notificações
public class NotificacaoWorker : BackgroundService
{
private readonly INotificacaoService _service;
public NotificacaoWorker(INotificacaoService service)
{
_service = service;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
await _service.EnviarPendentesAsync();
await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
}
}
}
🧭 Arquitetura Recomendada
Em aplicações modernas, recomenda-se separar os workers por responsabilidade:
src/
├── Workers/
│ ├── NotificacaoWorker.cs
│ ├── FilaWorker.cs
│ └── AgendadorWorker.cs
├── Application/ # Casos de uso
├── Domain/ # Regras de negócio
├── Infrastructure/ # Brokers, filas, logs, email
└── Shared/ # Utilitários comuns
Workers devem delegar a lógica para serviços de domínio ou da aplicação (não misturar responsabilidade dentro do worker).
✅ Boas práticas
- Mantenha os
Workers
leves — apenas orquestrando chamadas de serviços. - Use injeção de dependência (
IServiceScopeFactory
) para criar escopos. - Capture exceções e registre logs com contexto.
- Prefira usar bibliotecas como Polly para tolerância a falhas (retries, circuit breaker).
- Faça shutdowns respeitando o
CancellationToken
.
⚙️ Worker com escopo por operação
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using var scope = _scopeFactory.CreateScope();
var meuServico = scope.ServiceProvider.GetRequiredService<IMeuServico>();
await meuServico.ProcessarAsync();
await Task.Delay(5000, stoppingToken);
}
}
🚢 Publicação e Deploy
Você pode rodar Workers:
- Como serviço Windows:
sc create
,New-Service
- Em Linux (Systemd): criar unit
.service
- Em Docker:
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY ./publish .
ENTRYPOINT ["dotnet", "MeuWorkerApp.dll"]
📦 Quando usar um Worker em vez de uma API?
Situação | Use API? | Use Worker? |
---|---|---|
Exposição HTTP/REST | ✅ | ❌ |
Escuta contínua de fila | ❌ | ✅ |
Job de execução em horário fixo | ❌ | ✅ |
Processamento assíncrono em background | ❌ | ✅ |
Interface para usuário final | ✅ | ❌ |
🔚 Conclusão
Worker Services são componentes essenciais nas aplicações modernas .NET. Eles permitem construir soluções desacopladas, assíncronas, escaláveis e resilientes. Ao usá-los com bons princípios arquiteturais, você amplia o poder da sua aplicação sem comprometer manutenibilidade.
🤝 Conecte-se comigo
- 🌐 shifters.dev
- ✍️ Medium
- 📬 contato@dopme.io
Top comments (0)