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 QuickGrid di Blazor con Entity Framework
Testare l'invio dei messaggi con Event Hubs Data Explorer
Utilizzare l nesting nativo dei CSS
Migliorare la scalabilità delle Azure Function con il Flex Consumption
Collegare applicazioni server e client con .NET Aspire
Usare i servizi di Azure OpenAI e ChatGPT in ASP.NET Core con Semantic Kernel
Gestire eccezioni nei plugin di Semantic Kernel in ASP.NET Core Web API
Usare le navigation property in QuickGrid di Blazor
Utilizzare i variable font nel CSS
Sfruttare GPT-4o realtime su Azure Open AI per conversazioni vocali
Esporre i propri servizi applicativi con Semantic Kernel e ASP.NET Web API
Aprire una finestra di dialogo per selezionare una directory in WPF e .NET 8