S

super-dev — full-stack

@super-dev.app · Full-stack · ★ ouvert aux missions
12,8k abonnés·47 vidéos·Actif depuis 2017

Développeur full-stack .NET / Angular avec une casquette DevOps sur Azure Cloud. Aussi à l'aise sur Flutter + Firebase. Je construis des produits, je les déploie, je les surveille.

Retour aux articles
.NET
.NET

gRPC entre microservices .NET

Article 4 sur 5 — Le .NET moderne
APIs minimales, CQRS, gRPC, source generators : du .NET 8 net et testable, sans usine à gaz.

Entre microservices, le JSON sur HTTP/1.1 paie cher son confort : sérialisation verbeuse, pas de contrat fort, une connexion par appel. gRPC répond à ce contexte précis — du binaire compact sur HTTP/2, un contrat partagé et du code généré des deux côtés. En .NET, l'intégration est de première classe.

Le contrat .proto, source unique de vérité

Tout part d'un fichier .proto : il décrit les messages et le service, indépendamment du langage. C'est le contrat — ni le client ni le serveur ne l'écrivent à la main. On y déclare un service Pricing exposant un appel rpc GetQuote (QuoteRequest) qui renvoie un QuoteReply , chaque champ étant numéroté ( string sku = 1; , int32 quantity = 2; ) — ces numéros sont la clé de la compatibilité ascendante : on n'en réutilise jamais un.

Côté .NET, on référence ce fichier dans le .csproj via <Protobuf Include="pricing.proto" /> . Le package Grpc.Tools génère alors, à la compilation, la classe de base serveur et le client typé — aucun DTO à recopier :

C#
1// Généré par Grpc.Tools à partir de pricing.proto — ne pas éditer
2public partial class QuoteRequest
3{
4 public string Sku { get; set; }
5 public int Quantity { get; set; }
6}

Serveur et client typés

Le serveur dérive de la classe générée Pricing.PricingBase et redéfinit la méthode. Pas de routing à câbler, pas de désérialisation manuelle : on reçoit un message fortement typé.

C#
1public sealed class PricingService(IPriceBook book) : Pricing.PricingBase
2{
3 public override async Task<QuoteReply> GetQuote(
4 QuoteRequest request, ServerCallContext context)
5 {
6 var unitPrice = await book.LookupAsync(request.Sku, context.CancellationToken);
7
8 return new QuoteReply { UnitPriceCents = unitPrice * request.Quantity };
9 }
10}

Côté appelant, on n'écrit pas non plus de HttpClient . On injecte le client généré via AddGrpcClient , et on l'appelle comme une méthode locale :

C#
1builder.Services.AddGrpcClient<Pricing.PricingClient>(options =>
2 options.Address = new Uri("https://pricing:443"));

Le streaming, l'argument décisif

Là où REST plafonne, gRPC excelle : HTTP/2 permet le streaming dans les deux sens. Un stream côté serveur pousse des résultats au fil de l'eau ; un stream bidirectionnel ouvre un canal full-duplex idéal pour la télémétrie ou le chat. On écrit dans un IServerStreamWriter<T> et le client itère avec await foreach — sans polling, sans WebSocket à bricoler.

gRPC contre REST : choisir en connaissance de cause

gRPC n'est pas universel. Ses points forts — binaire compact, contrat fort, streaming, latence faible — en font l'outil interne par excellence (service-à-service). Ses limites sont réelles : un navigateur ne parle pas gRPC nativement (il faut gRPC-Web et un proxy), le binaire n'est pas lisible à l'œil, et le débogage demande des outils dédiés. Pour une API publique consommée par des tiers, REST/JSON reste souvent le bon choix. Le guide Microsoft compare les deux dans la doc gRPC pour .NET .

Le réflexe sain : REST en façade publique, gRPC à l'intérieur . Le contrat .proto devient alors la frontière formelle entre vos services — versionnée, partagée, vérifiée par le compilateur.
super-dev — portfolio.app
// Continuer dans .NET
{ }
Étrangler un monolithe .NET 8 sans tout casser
9 min • 3,2k lectures
ƒ()
Minimal APIs + EF Core : une API .NET 8 propre
8 min • 3,1k lectures
CQRS et vertical slices sans usine à gaz
7 min • 2,3k lectures