Sfruttare la cache in un tag helper di ASP.NET Core MVC

di Moreno Gentili, in ASP.NET Core,

In ogni tipo di applicazione web, le funzionalità di caching sono importanti per ottenere notevoli vantaggi prestazionali che si misurano in tempi di caricamento ridotti e in un maggior numero di richieste contemporanee che il server è in grado di gestire.

Con ASP.NET Core MVC abbiamo varie opportunità, una delle quali consiste nell'usare il tag helper Cache attorno alle porzioni di pagina che intendiamo inserire in cache.

In questo esempio, il primo paragrafo si trova all'interno del tag helper Cache e perciò verrà elaborato dal server soltanto durante la prima visita di pagina, per poi essere inserito in cache.

<cache>
  <p>Ora corrente (dalla cache): @DateTime.Now</p>
</cache>
<p>Ora corrente (non in cache): @DateTime.Now</p>

Ad ogni successiva richiesta di pagina, il contenuto del primo paragrafo verrà tratto dalla cache. Il secondo paragrafo continuerà ad essere elaborato dal server ogni volta. E' facilmente verificabile osservando l'output di pagina.


Grazie al tag , usiamo un approccio dichiarativo che mantiene la pagina decisamente facile da leggere. Inoltre, il tag supporta svariati attributi che ci permettono di configurare il comportamento della cache.

Configurare il periodo di permanenza in cache

Il primo aspetto che ci interessa configurare è il tempo di permanenza di un contenuto in cache. Infatti, è importante che i contenuti prima o poi scadano per essere rigenerati sulla base di informazioni più recenti. A tale scopo, disponiamo di tre attributi:

  • expires-after da valorizzare con un TimeSpan per indicare un periodo di tempo, trascorso il quale, il contenuto dovrà essere rigenerato;
  • expires-sliding da valorizzare anch'esso con un TimeSpan che indica un periodo di inattività. Ogni volta che il contenuto viene letto dalla cache, la sua rimozione viene rimandata;
  • expires-on per indicare un DateTime che rappresenta una data assoluta di scadenza.

@* I due DateTime visualizzati qui divergeranno al massimo di 10 secondi *@
<cache expires-after="@TimeSpan.FromSeconds(10)">
  <p>Ora corrente (dalla cache): @DateTime.Now</p>
</cache>
<p>Ora corrente (non in cache): @DateTime.Now</p>

Configurare il criterio di inserimento in cache

Tutto il contenuto che si trova all'interno del tag viene generato dal server e poi aggiunto in cache con una particolare chiave calcolata in modo deterministico. Tale chiave, che dipende dai valori degli attributi vary-by- e dai dati della richiesta HTTP corrente, verrà anche usata in un secondo momento per recuperare un contenuto dalla cache.

  • vary-by-route lo valorizziamo con il nome di un route parameter come "id", per indicare che il contenuto deve essere rigenerato al variare dell'id della risorsa che stiamo visualizzando;
  • vary-by-query il contenuto viene generato e messo in cache al variare della chiave querystring indicata;
  • vary-by-user va impostato a true quando visualizziamo dati specifici per l'utente loggato come ad esempio il riquadro del suo profilo, contenente il nome e la foto.
  • vary-by-header per far variare la cache in base ad un'intestazione della richiesta HTTP, come ad esempio "Accept-Language" se la stiamo usando per visualizzare contenuti in lingua;
  • vary-by-cookie permette di far variare la cache in base al contenuto di un cookie, di cui dobbiamo indicare il nome.

E' possibile usare uno o più attributi vary-by- per realizzare politiche di caching avanzate, pur con la dovuta cautela.

Il tag helper Cache, infatti, si affida ad un'implementazione di IMemoryCache che usa la memoria RAM del server come spazio di archiviazione. Per questo motivo, è importante farne un uso accorto. L'obiettivo è tenere in cache solo i contenuti particolarmente costosi da generare per il server o che vengono visualizzati di frequente.

@* In questo blocco visualizzo i prezzi di un prodotto del catalogo.
Dato che i prezzi devono essere calcolati per ogni prodotto in base all'utente loggato,
allora uso una combinazione di vary-by-route e vary-by-user *@
<cache vary-by-route="id" vary-by-user="true" expires-on="@DateTime.Today.AddDays(1)">
    @* Qui invoco il view component della tabella prezzi *@
</cache>

Configurare la priorità

Se il webserver dovesse trovarsi con poca RAM disponibile, le nostre copie cache inizieranno ad essere progressivamente rimosse per liberare memoria.
L'attributo priority accetta i valori dell'enumerazione CacheItemPriority per determinare la prorità di permanenza in cache di un contenuto, a partire dal valore Low, che rappresenta una priorità minima, a NeverRemove che invece eviterà la rimozione del contenuto dalla memoria.

Conclusioni

Abbiamo visto come il tag helper Cache sia estremamente semplice da usare e versatile nella sua configurazione. Tuttavia, se la nostra applicazione gira in webfarm, usare un meccanismo di caching locale potrebbe non essere la soluzione migliore. Per fare in modo che la cache sia condivisa tra tutti i webserver, possiamo valutare l'uso di un meccanismo di caching distribuito, che esamineremo in un prossimo script.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi