Nel precedente script ci siamo occupati di come attivare il caching tramite il tag helper cache in ASP.NET Core MVC. Questa funzionalità, purtroppo, è forzatamente agganciata a un provider cache in memory (IMemoryCache) e pertanto non è adatta a scenari distribuiti, quando vogliamo condividere le informazioni di cache tra più server.
Un tipico esempio è se effettuiamo il deploy dell'applicazione su una Web App di Azure, configurata su più istanze: ognuna avrà la propria cache in memory, separata da tutte le altre, che dovrà essere comunque caricata, con il risultato di limitare l'effetto benefico del caching stesso.
Alternativamente possiamo sfruttare un sistema di cache distribuita, come per esempio Redis Cache su Azure, tramite il servizio IDistributedCache. Il corrispondente provider è implementato dal package Microsoft.Extensions.Caching.Redis che dobbiamo installare preventivamente.
Install-Package Microsoft.Extensions.Caching.Redis
Il primo passo, come al solito, è quello di configurare il servizio su startup.cs, all'interno del metodo ConfigureServices:
public void ConfigureServices(IServiceCollection services) { // Add framework services. // ... altri servizi ... services.AddDistributedRedisCache(cfg => { cfg.Configuration = Configuration.GetConnectionString("redis"); }); }
In questo modo, abbiamo indicato al framework che vogliamo connetterci a un'istanza di Redis Cache la cui connection string è memorizzata in appsetting.json:
{ "ConnectionStrings": { "Redis": "..." } }
Se stiamo usando Redis Cache di Azure, possiamo reperire questo dato tramite l'opzione AccessKeys:
A questo punto abbiamo configurato il servizio IDistributedCache all'interno dell'IoC container di ASP.NET Core, e siamo quindi in grado di recuperarlo da un qualsiasi controller, semplicemente aggiungendolo come parametro al costruttore:
public class HomeController : Controller { private IDistributedCache _cache; public HomeController(IDistributedCache cache) { _cache = cache; } public async Task<IActionResult> Index() { var currentDate = await _cache.GetStringAsync("currentDate"); if (currentDate == null) { currentDate = DateTime.Now.ToString(); await _cache.SetStringAsync("currentDate", currentDate, new DistributedCacheEntryOptions() { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(10) }); } ViewBag.CurrentDate = currentDate; return View(); } }
Lo snippet in alto sfrutta questo cache provider per memorizzare la data corrente in cache per 10 secondi. Esistono anche altre proprietà all'interno di DistributedCacheEntryOptions per configurare una scadenza assoluta o una sliding expiration, che si rinnova automaticamente ogni volta che il dato viene consumato.
Una sensibile differenza rispetto al normale provider di cache in memory è che, in fin dei conti, i dati in questo caso devono essere trasferiti su un server esterno e, pertanto, non possiamo memorizzare un qualsiasi oggetto: normalmente il provider di Redis accetta esclusivamente array di byte, ma con gli helper GetStringAsync e SetStringAsync possiamo usare oggetti di tipo string che sono sicuramente più comodi.
Anche in questo caso, come per IMemoryCache, esiste un corrispondente tag helper da sfruttare in pagina per effettuare il caching di un segmento di HTML:
<distributed-cache name="cachedDate1" expires-after="TimeSpan.FromSeconds(10)"> <h1>Ora corrente: @DateTime.Now.ToString()</h1> </distributed-cache> <h1>Ora corrente: @DateTime.Now.ToString()</h1>
Un ultima considerazione va fatta sulle prestazioni: sfruttare una cache distribuita è una condizione ben diversa da una cache in memory. Sebbene infatti Redis Cache sia estremamente veloce, comunque essa impone una connessione a un host remoto e un trasferimento di rete. Il vantaggio però è che il dato è immediatamente disponibile per ogni macchina della nostra web farm, con un grosso beneficio dal punto di vista della scalabilità, perchè consente di spostare il carico da una risorsa, come ad esempio il database, verso un'altra che è appositamente costruita per essere scalabile e veloce.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Utilizzare gli snapshot con Azure File shares
Accesso sicuro ai secrets attraverso i file in Azure Container Apps
Effettuare lo stream della risposta in ASP.NET Core tramite IAsyncEnumerable
Gestire domini wildcard in Azure Container Apps
Usare una container image come runner di GitHub Actions
Applicare il versioning ai nostri endpoint ASP.NET Core Minimal API
Recuperare un elemento inserito nella cache del browser tramite API JavaScript
Supportare il sorting di dati tabellari in Blazor con QuickGrid
Eseguire attività pianificate con Azure Container Jobs
Sfruttare MQTT in cloud e in edge con Azure Event Grid
Gestire errori funzionali tramite exception in ASP.NET Core Web API
Autenticarsi in modo sicuro su Azure tramite GitHub Actions
I più letti di oggi
- PWAConf 2020 - Online
- Reactive form tipizzati con FormBuilder in Angular
- Utilizzare ChatGPT con Azure OpenAI
- Mantenere sempre reattiva una Lambda di AWS
- Messaggi in tempo reale con Blazor Server
- Una chat con #aspnetcore e #websockets https://aspit.co/bmh di @GentiliMoreno #webapi #aspnetcore2
- Autenticarsi in modo sicuro su Azure tramite GitHub Actions
- Effettuare il multi-checkout in linea nelle pipeline di Azure DevOps
- Creare una MarkupExtension per accedere alle proprietà statiche in Silverlight 5.0
- Navigare la struttura visuale di un UIElement fino a recuperare l'elemento logico in Silverlight 3.0