Negli ultimi due script abbiamo trattato alcuni accorgimenti che ci permettono di rendere la nostra applicazione più resistente a malfunzionamenti che possono accadere ai servizi a cui accede. Nel farlo, abbiamo introdotto l'uso di Polly (https://github.com/App-vNext/Polly), una libreria open source che espone tutta una serie di pattern estremamente utili, come Retry, Circuit Breaker, Fallback, ecc.
In questo script, ci occuperemo della gestione dei Timeout. Quando accediamo a risorse esterne, è sempre un ottimo accorgimento darsi un tempo limite entro cui la chiamata al servizio debba essere completata. La motivazione è molto semplice: un servizio che non risponde nel tempo "usuale", molto probabilmente non risponderà mai, pertanto è meglio terminare in anticipo la richiesta senza attendere troppo.
Altrimenti, potremmo trovarci ad attendere per secondi che una risorsa non disponibile ci palesi il suo stato, con il solo risultato di aver fatto aspettare l'utente più del dovuto.
Questo accorgimento è particolarmente importante anche nei casi in cui dobbiamo rispettare una Service Level Agreement (SLA), e non vogliamo essere troppo penalizzati dalle prestazioni delle nostre dipendenze.
Come gestirlo con Polly? Al solito, il primo passo è sempre quello di installare il relativo package NuGet:
install-package Polly
A questo punto, in Startup.cs, possiamo definire una TimeoutPolicy come la seguente, per terminare l'esecuzione dopo - per esempio - 500ms:
public void ConfigureServices(IServiceCollection services) { // .. altri servizi .. var timeout = Policy .Timeout(TimeSpan.FromMilliseconds(500), TimeoutStrategy.Pessimistic); services.AddSingleton<TimeoutPolicy>(timeout); }
Ora possiamo spostarci sul controller e utilizzarla per invocare il servizio:
public HomeController(IContentService content, TimeoutPolicy timeout) { _content = content; _timeout = timeout; } public async Task<IActionResult> Index() { string[] articles; Stopwatch watch = Stopwatch.StartNew(); try { articles = await _timeout.Execute( async () => await _content.LoadArticlesAsync()); } catch (Exception ex) { articles = new[] { "Articoli non disponibili al momento" }; } watch.Stop(); ViewBag.Time = $"{watch.ElapsedMilliseconds} ms"; return View(articles); }
Il controller accetta la policy che abbiamo configurato come parametro nel costruttore e, nella action Index, ne sfrutta il metodo Execute per invocare LoadArticlesAsync. Se l'esecuzione non dovesse terminare entro i 500ms stabiliti, questo metodo solleverà una TimeoutRejectException e verrà mostrato il messaggio "articoli non disponibili" all'utente.
Il beneficio, come già detto, è che l'attesa durerà al più 500ms, anche se il servizio - lo si può notare dal codice allegato - è fatto in modo di durare per ben 10 secondi.
Prima di concludere vale la pena spendere due parole su cosa accade al delegate eseguito in caso si verifichi il timeout. Contrariamente a ciò che potremmo aspettarci, l'esecuzione del metodo LoadArticlesAsync verrà comunque completata: Polly si limita infatti a restituire il controllo al chiamante entro il timeout, ma non effettua l'abort del delegate per non rischiare di compromettere lo stato della nostra applicazione. Questa strategia di esecuzione prende il nome di Pessimistic, come abbiamo specificato in fase di configurazione:
var timeout = Policy .Timeout(TimeSpan.FromMilliseconds(500), TimeoutStrategy.Pessimistic);
La modalità di default, invece, si basa sulla strategia Optimistic, che sfrutta il concetto di CancellationToken per terminare in maniera "graceful" l'esecuzione del metodo. Ne mostreremo un esempio di utilizzo nel prossimo script.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Inference di dati strutturati da testo con Semantic Kernel e ASP.NET Core Web API
Ottimizzazione dei block template in Angular 17
Sfruttare MQTT in cloud e in edge con Azure Event Grid
Aggiungere interattività lato server in Blazor 8
Effettuare il binding di date in Blazor
Effettuare il log delle chiamate a function di GPT in ASP.NET Web API
gRPC con .NET
Sfruttare i KeyedService in un'applicazione Blazor in .NET 8
Gestire il colore CSS con HWB
Utilizzare politiche di resiliency con Azure Container App
Cambiare la chiave di partizionamento di Azure Cosmos DB
Utilizzare il metodo CountBy di LINQ per semplificare raggruppamenti e i conteggi
I più letti di oggi
- Effettuare il log delle chiamate a function di GPT in ASP.NET Web API
- ecco tutte le novità pubblicate sui nostri siti questa settimana: https://aspit.co/wkly buon week-end!
- Utilizzare il metodo CountBy di LINQ per semplificare raggruppamenti e i conteggi
- Creare una libreria CSS universale: Cards
- Eseguire script pre e post esecuzione di un workflow di GitHub