Microsserviços em C#: da teoria à prática no .NET
A arquitetura de microsserviços tornou-se o padrão para construir aplicações escaláveis e tolerantes a falhas. A plataforma .NET (C#) fornece todas as ferramentas necessárias para criar tais sistemas: desde suporte integrado a contêineres até frameworks poderosos para comunicação entre serviços. Neste artigo, vamos analisar os princípios-chave da construção de microsserviços em C# e examinar exemplos práticos de código.
1. Fundamentos da arquitetura de microsserviços no .NET
Microsserviços são uma abordagem onde a aplicação é dividida em serviços independentes e fracamente acoplados. Cada serviço é responsável por sua própria função de negócio e pode ser desenvolvido, implantado e escalado independentemente dos outros.
Princípios-chave para o desenvolvedor .NET:
- Responsabilidade Única (Single Responsibility) — cada microsserviço resolve uma única tarefa.
- Independência de dados — cada serviço tem seu próprio banco de dados (Database per Service).
- Acoplamento Fraco (Loose Coupling) — os serviços se comunicam via API, não através de memória compartilhada.
- Autonomia — o serviço pode ser alterado e reimplantado sem parar todo o sistema.
Para criar um novo projeto de microsserviço em C#, use o comando:
dotnet new webapi -n UserServicedotnet new webapi -n OrderServicedotnet new webapi -n NotificationServiceCada projeto recebe seu próprio Program.cs, configurações e dependências.
2. Comunicação entre serviços: REST e gRPC
No .NET, existem duas abordagens principais para comunicação entre microsserviços: síncrona (REST/gRPC) e assíncrona (através de brokers de mensagens). Vamos analisar ambas.
REST API usando HttpClient
A maneira mais simples é usar HttpClientFactory para criar um cliente tipado.
// No Program.cs do serviço OrderServicebuilder.Services.AddHttpClient<IUserServiceClient, UserServiceClient>(client =>{ client.BaseAddress = new Uri("http://userservice:5000");});
// UserServiceClient.cspublic class UserServiceClient : IUserServiceClient{ private readonly HttpClient _httpClient;
public UserServiceClient(HttpClient httpClient) { _httpClient = httpClient; }
public async Task<UserDto> GetUserAsync(int userId) { var response = await _httpClient.GetAsync($"/api/users/{userId}"); response.EnsureSuccessStatusCode(); return await response.Content.ReadFromJsonAsync<UserDto>(); }}Recomendação: use Polly (biblioteca para .NET) para implementar políticas de retry e Circuit Breaker.
gRPC para cenários de alto desempenho
gRPC funciona sobre HTTP/2 e usa Protocol Buffers para serialização. Isso é significativamente mais rápido que JSON.
// Definição do serviço em user.protoservice UserGrpcService { rpc GetUser (GetUserRequest) returns (UserResponse);}
// Código do servidor em C#public class UserGrpcServiceImpl : UserGrpcService.UserGrpcServiceBase{ public override Task<UserResponse> GetUser(GetUserRequest request, ServerCallContext context) { var user = _dbContext.Users.Find(request.UserId); return Task.FromResult(new UserResponse { Id = user.Id, Name = user.Name, Email = user.Email }); }}3. Gerenciamento de dados e transações
Em microsserviços, cada banco de dados pertence a apenas um serviço. Isso elimina consultas SQL diretas entre serviços. Para trabalhar com dados no .NET, o padrão é o Entity Framework Core.
Exemplo de configuração do DbContext para um microsserviço
public cla