Il punto focale di una comunicazione gRPC è la creazione di un canale di comunicazione, il GrpcChannel. Attraverso questo canale passeranno tutte le richieste che il client invierà al server, e di conseguenza le risposte inoltrate dal server verso il chiamante.
Il GrpcChannel non è però un oggetto perfetto, tutt'altro: contrariamente a quanto avviene in una comunicazione WebAPI, in cui il ciclo di vita inizia nel momento della chiamata e termina alla ricezione della risposta, il canale di comunicazione gRPC può essere mantenuto attivo per più chiamate, e deve supportare una comunicazione basata sullo stream di dati, nella quale il server, o il client, inviano periodicamente nuovi dati all'interno della stessa chiamata.
Questa modalità di trasferimento di informazioni rende il GrpcChannel soggetto a errori temporanei, o Transient fault, che possono, anche per pochi istanti, interrompere la comunicazione con il server, andando ad invalidare tutte le chiamate in corso. Errori dovuti principalmente a perdita di connessione, indisponibilità del servizio o server timeout.
Fino ad ASP.NET Core 5 l'unico meccanismo di protezione verso questo tipo di errori, era l'implementazione di una logica basata sulla gestione di un'eccezione di tipo RpcException, come mostrato nel seguente codice:
var client = new Greeter.GreeterClient(channel); try { var response = await client.SayHelloAsync( new HelloRequest { Name = "Morgan" }); Console.WriteLine(response.Message); } catch (RpcException ex) { // Logica di retry }
Questo metodo richiedeva però la duplicazione di molto codice all'interno dell'applicazione: ovunque si fosse instaurato un canale di comunicazione avremmo dovuto gestire l'errore.
In ASP.NET Core 6 il canale supporta una logica di retry automatica basata su una configurazione, iniettata nel momento della creazione del canale.
var defaultMethodConfig = new MethodConfig { Names = { MethodName.Default }, RetryPolicy = new RetryPolicy { MaxAttempts = 5, InitialBackoff = TimeSpan.FromSeconds(1), MaxBackoff = TimeSpan.FromSeconds(5), BackoffMultiplier = 1.5, RetryableStatusCodes = { StatusCode.Unavailable } } }; var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } } });
La configurazione permette il settaggio di vari parametri:
- MaxAttemps: numero massimo di tentativi di retry
- InitialBackoff: tempo di attesa per il primo retry
- BackoffMultiplier: moltiplicatore del tempo di attesa dopo il primo retry
- MaxBackoff: tempo massimo di attesa prima di retry, mette un limite al valore che il moltiplicatore può generare
- RetryableStatusCodes: occasione nella quale eseguire la logica di retry
Il codice mostrato all'inizio non necessiterà più del blocco try/catch, venendo così riscritto:
var client = new Greeter.GreeterClient(channel); var response = await client.SayHelloAsync( new HelloRequest { Name = "Morgan" }); Console.WriteLine(response.Message);
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Utilizzare parametri a livello di controller nel routing di ASP.NET Core
GitHub <3 .NET
Log streaming di una Azure Container App
YARP: un reverse proxy in ASP.NET Core
Gestire il fallimento di uno step in un workflow di GitHub
Utilizzare la parola chiave var con lambda eExpression e method group in C# 10
Parallelizzare le chiamate HTTP con async/await e le Promise in JavaScript
Utilizzare il metodo Chunk per creare blocchi di oggetti di uguali dimensioni partendo da una lista
Velocizzare l'installazione delle dipendenze in un workflow di GitHub
Creare Higher-Order functions in JavaScript
Ottimizzare le performance di serializzazione e deserializzazione JSON con System.Text.Json e i source generators
Limitare lo spazio dei repository di Azure Container Registry con uno script bash e Azure CLI
I più letti di oggi
- Linting di un Dockerfile con un workflow di GitHub
- Sfruttare la local cache del browser tramite gli ETag in #aspnetcore https://aspit.co/cfc di @crad77 #webapi #aspnetmvc #blazor #cache
- 3 metodi JavaScript che ogni applicazione web dovrebbe contenere - Parte 2
- Monitorare i server on-premises con Azure Arc