Microservices en C# : de la théorie à la pratique sur .NET
L'architecture microservices est devenue la norme pour construire des applications évolutives et résilientes. La plateforme .NET (C#) fournit tous les outils nécessaires pour créer de tels systèmes : du support intégré pour la conteneurisation aux frameworks puissants pour la communication inter-services. Dans cet article, nous allons analyser les principes clés de la construction de microservices en C# et examiner des exemples de code pratiques.
1. Fondamentaux de l'architecture microservices sur .NET
Les microservices sont une approche où l'application est divisée en services indépendants et faiblement couplés. Chaque service est responsable de sa propre fonction métier et peut être développé, déployé et mis à l'échelle indépendamment des autres.
Principes clés pour le développeur .NET :
- Responsabilité unique (Single Responsibility) — chaque microservice résout une seule tâche.
- Indépendance des données — chaque service possède sa propre base de données (Database per Service).
- Couplage faible (Loose Coupling) — les services communiquent via API, et non via une mémoire partagée.
- Autonomie — un service peut être modifié et redéployé sans arrêter l'ensemble du système.
Pour créer un nouveau projet de microservice en C#, utilisez la commande :
dotnet new webapi -n UserServicedotnet new webapi -n OrderServicedotnet new webapi -n NotificationServiceChaque projet reçoit son propre Program.cs, ses configurations et ses dépendances.
2. Communication inter-services : REST et gRPC
Dans .NET, il existe deux approches principales pour la communication entre microservices : synchrone (REST/gRPC) et asynchrone (via des courtiers de messages). Examinons les deux.
API REST avec HttpClient
La méthode la plus simple consiste à utiliser HttpClientFactory pour créer un client typé.
// Dans Program.cs du service 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>(); }}Recommandation : utilisez Polly (bibliothèque pour .NET) pour implémenter des politiques de tentatives et le Circuit Breaker.
gRPC pour les scénarios haute performance
gRPC fonctionne sur HTTP/2 et utilise Protocol Buffers pour la sérialisation. C'est considérablement plus rapide que JSON.
// Définition du service dans user.protoservice UserGrpcService { rpc GetUser (GetUserRequest) returns (UserResponse);}
// Code serveur 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. Gestion des données et transactions
Dans les microservices, chaque base de données appartient à un seul service. Cela exclut les requêtes SQL directes entre services. Pour travailler avec les données dans .NET, la norme est Entity Framework Core.
Exemple de configuration DbContext pour un microservice
public cla