Microservicios en C#: de la teoría a la práctica en .NET
La arquitectura de microservicios se ha convertido en el estándar para construir aplicaciones escalables y tolerantes a fallos. La plataforma .NET (C#) proporciona todas las herramientas necesarias para crear dichos sistemas: desde soporte integrado para contenedores hasta potentes frameworks para la comunicación entre servicios. En este artículo analizaremos los principios clave para construir microservicios en C# y veremos ejemplos prácticos de código.
1. Fundamentos de la arquitectura de microservicios en .NET
Los microservicios son un enfoque en el que una aplicación se divide en servicios independientes y débilmente acoplados. Cada servicio se encarga de una función de negocio específica y puede desarrollarse, implementarse y escalarse de forma independiente de los demás.
Principios clave para el desarrollador .NET:
- Responsabilidad Única (Single Responsibility) — cada microservicio resuelve una única tarea.
- Independencia de datos — cada servicio tiene su propia base de datos (Database per Service).
- Acoplamiento Débil (Loose Coupling) — los servicios se comunican a través de API, no mediante memoria compartida.
- Autonomía — un servicio puede modificarse y redistribuirse sin detener todo el sistema.
Para crear un nuevo proyecto de microservicio en C#, use el comando:
dotnet new webapi -n UserServicedotnet new webapi -n OrderServicedotnet new webapi -n NotificationServiceCada proyecto obtiene su propio Program.cs, configuraciones y dependencias.
2. Comunicación entre servicios: REST y gRPC
En .NET existen dos enfoques principales para la comunicación entre microservicios: síncrono (REST/gRPC) y asíncrono (a través de brokers de mensajes). Analicemos ambos.
API REST con HttpClient
La forma más sencilla es usar HttpClientFactory para crear un cliente tipado.
// En Program.cs del servicio 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>(); }}Recomendación: use Polly (biblioteca para .NET) para implementar políticas de reintentos y Circuit Breaker.
gRPC para escenarios de alto rendimiento
gRPC funciona sobre HTTP/2 y utiliza Protocol Buffers para la serialización. Esto es significativamente más rápido que JSON.
// Definición del servicio en user.protoservice UserGrpcService { rpc GetUser (GetUserRequest) returns (UserResponse);}
// Código del servidor en 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. Gestión de datos y transacciones
En microservicios, cada base de datos pertenece únicamente a un servicio. Esto elimina las consultas SQL directas entre servicios. Para trabajar con datos en .NET, el estándar es Entity Framework Core.
Ejemplo de configuración de DbContext para un microservicio
public cla