Memorizzazione nella cache distribuita in ASP.NET Core
Di Mohsin Nasir e smandia
Nota
Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 8 di questo articolo.
Avviso
Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere Criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 8 di questo articolo.
Importante
Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Per la versione corrente, vedere la versione .NET 8 di questo articolo.
Una cache distribuita è una cache condivisa da più server app, in genere gestita come servizio esterno ai server app che vi accedono. Una cache distribuita può migliorare le prestazioni e la scalabilità di un'app ASP.NET Core, soprattutto quando l'app è ospitata da un servizio cloud o da una server farm.
Una cache distribuita offre diversi vantaggi rispetto ad altri scenari di memorizzazione nella cache in cui i dati memorizzati nella cache vengono archiviati in singoli server app.
Quando i dati memorizzati nella cache vengono distribuiti, i dati:
- Coerente (coerente ) tra le richieste a più server.
- Sopravvive ai riavvii del server e alle distribuzioni di app.
- Non usa memoria locale.
La configurazione della cache distribuita è specifica dell'implementazione. Questo articolo descrive come configurare le cache distribuite di SQL Server e Redis. Sono disponibili anche implementazioni di terze parti, ad esempio NCache (NCache in GitHub). Indipendentemente dall'implementazione selezionata, l'app interagisce con la cache usando l'interfaccia IDistributedCache .
Visualizzare o scaricare il codice di esempio (procedura per il download)
Avviso
Questo articolo usa un database locale che non richiede l'autenticazione dell'utente. Le app di produzione devono usare il flusso di autenticazione più sicuro disponibile. Per altre informazioni sull'autenticazione per le app di test e produzione distribuite, vedere Proteggere i flussi di autenticazione.
Prerequisiti
Aggiungere un riferimento al pacchetto per il provider di cache distribuita usato:
- Per una cache distribuita Redis, Microsoft.Extensions.Caching.StackExchangeRedis.
- Per SQL Server, Microsoft.Extensions.Caching.SqlServer.
- Per la cache distribuita NCache, NCache.Microsoft.Extensions.Caching.OpenSource.
Interfaccia IDistributedCache
L'interfaccia IDistributedCache fornisce i metodi seguenti per modificare gli elementi nell'implementazione della cache distribuita:
- Get, GetAsync: accetta una chiave stringa e recupera un elemento memorizzato nella cache come
byte[]
matrice, se presente nella cache. - Set, SetAsync: aggiunge un elemento (come
byte[]
matrice) alla cache usando una chiave stringa. - Refresh, RefreshAsync: aggiorna un elemento nella cache in base alla relativa chiave, reimpostando il timeout di scadenza scorrevole (se presente).
- Remove, RemoveAsync: rimuove un elemento della cache in base alla relativa chiave stringa.
Stabilire servizi di memorizzazione nella cache distribuita
Registrare un'implementazione di IDistributedCache in Program.cs
. Le implementazioni fornite dal framework descritte in questo argomento includono:
- Cache Redis distribuita
- Cache di memoria distribuita
- Cache di SQL Server distribuita
- Cache NCache distribuita
- Cache di Azure CosmosDB distribuita
Cache Redis distribuita
È consigliabile che le app di produzione usino la cache Redis distribuita perché è la più efficiente. Per altre informazioni, vedere Raccomandazioni.
Redis è un archivio dati open source in memoria, che viene spesso usato come cache distribuita. È possibile configurare un cache di Azure per Redis per un'app ASP.NET Core ospitata in Azure e usare un cache di Azure per Redis per lo sviluppo locale.
Un'app configura l'implementazione della cache usando un'istanza RedisCache di chiamando AddStackExchangeRedisCache. Per la memorizzazione nella cache dell'output, usare AddStackExchangeRedisOutputCache
.
- Creare un cache di Azure per Redis.
- Copiare il stringa di connessione primario (StackExchange.Redis) in Configurazione.
- Sviluppo locale: salvare il stringa di connessione con Secret Manager.
- Azure: salvare i stringa di connessione in un archivio sicuro, ad esempio Azure Key Vault
Il codice seguente abilita il cache di Azure per Redis:
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("MyRedisConStr");
options.InstanceName = "SampleInstance";
});
Il codice precedente presuppone che il stringa di connessione primario (StackExchange.Redis) sia stato salvato nella configurazione con il nome MyRedisConStr
della chiave .
Per altre informazioni, vedere Azure Cache for Redis.
Vedere questo problema di GitHub per una discussione sugli approcci alternativi a una cache Redis locale.
Cache di memoria distribuita
La cache di memoria distribuita (AddDistributedMemoryCache) è un'implementazione fornita dal framework di IDistributedCache che archivia gli elementi in memoria. La cache di memoria distribuita non è una cache distribuita effettiva. Gli elementi memorizzati nella cache vengono archiviati dall'istanza dell'app nel server in cui è in esecuzione l'app.
La cache di memoria distribuita è un'implementazione utile:
- Negli scenari di sviluppo e test.
- Quando un singolo server viene usato nell'ambiente di produzione e nel consumo di memoria non è un problema. L'implementazione della cache di memoria distribuita astrae l'archiviazione dei dati memorizzata nella cache. Consente di implementare una vera soluzione di memorizzazione nella cache distribuita in futuro se sono necessari più nodi o tolleranza di errore.
L'app di esempio usa cache di memoria distribuita quando l'app viene eseguita nell'ambiente di sviluppo in Program.cs
:
builder.Services.AddDistributedMemoryCache();
Cache di SQL Server distribuita
L'implementazione della cache di SQL Server distribuita (AddDistributedSqlServerCache) consente alla cache distribuita di usare un database di SQL Server come archivio di backup. Per creare una tabella di elementi memorizzata nella cache di SQL Server in un'istanza di SQL Server, è possibile usare lo sql-cache
strumento . Lo strumento crea una tabella con il nome e lo schema specificati.
Creare una tabella in SQL Server eseguendo il sql-cache create
comando . Specificare l'istanza di SQL Server (Data Source
), il database (Initial Catalog
), lo schema (ad esempio, dbo
) e il nome della tabella (ad esempio, TestCache
):
dotnet sql-cache create "Data Source=(localdb)/MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache
Viene registrato un messaggio per indicare che lo strumento ha avuto esito positivo:
Table and index were created successfully.
La tabella creata dallo sql-cache
strumento ha lo schema seguente:
Nota
Un'app deve modificare i valori della cache usando un'istanza di IDistributedCache, non un oggetto SqlServerCache.
L'app di esempio implementa SqlServerCache in un ambiente non di sviluppo in Program.cs
:
builder.Services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString(
"DistCache_ConnectionString");
options.SchemaName = "dbo";
options.TableName = "TestCache";
});
Nota
Un ConnectionString oggetto (e facoltativamente SchemaName e TableName) viene in genere archiviato all'esterno del controllo del codice sorgente (ad esempio, archiviato da Secret Manager o nei appsettings.json
/appsettings.{Environment}.json
file). Il stringa di connessione può contenere credenziali che devono essere mantenute fuori dai sistemi di controllo del codice sorgente.
Cache NCache distribuita
NCache è una cache distribuita in memoria open source sviluppata in modo nativo in .NET e .NET Core. NCache funziona sia in locale che configurato come cluster di cache distribuita per un'app ASP.NET Core in esecuzione in Azure o in altre piattaforme di hosting.
Per installare e configurare NCache nel computer locale, vedere Guida introduttiva per Windows (.NET e .NET Core).
Per configurare NCache:
- Installare NuGet open source NCache.
- Configurare il cluster della cache in client.ncconf.
- Aggiungere il codice seguente a
Program.cs
:
builder.Services.AddNCacheDistributedCache(configuration =>
{
configuration.CacheName = "democache";
configuration.EnableLogs = true;
configuration.ExceptionsEnabled = true;
});
Cache di Azure CosmosDB distribuita
Azure Cosmos DB può essere usato in ASP.NET Core come provider di stato della sessione usando l'interfaccia IDistributedCache
. Azure Cosmos DB è un database noSQL e relazionale completamente gestito per lo sviluppo di app moderne che offre disponibilità elevata, scalabilità e accesso a bassa latenza ai dati per applicazioni cruciali.
Dopo aver installato il pacchetto NuGet Microsoft.Extensions.Caching.Cosmos , configurare una cache distribuita di Azure Cosmos DB come indicato di seguito:
Riutilizzare un client esistente
Il modo più semplice per configurare la cache distribuita consiste nel riutilizzare un client Azure Cosmos DB esistente. In questo caso, l'istanza CosmosClient
non verrà eliminata quando il provider viene eliminato.
services.AddCosmosCache((CosmosCacheOptions cacheOptions) =>
{
cacheOptions.ContainerName = Configuration["CosmosCacheContainer"];
cacheOptions.DatabaseName = Configuration["CosmosCacheDatabase"];
cacheOptions.CosmosClient = existingCosmosClient;
cacheOptions.CreateIfNotExists = true;
});
Creare un nuovo client
In alternativa, creare un'istanza di un nuovo client. In questo caso, l'istanza CosmosClient
verrà eliminata quando il provider viene eliminato.
services.AddCosmosCache((CosmosCacheOptions cacheOptions) =>
{
cacheOptions.ContainerName = Configuration["CosmosCacheContainer"];
cacheOptions.DatabaseName = Configuration["CosmosCacheDatabase"];
cacheOptions.ClientBuilder = new CosmosClientBuilder(Configuration["CosmosConnectionString"]);
cacheOptions.CreateIfNotExists = true;
});
Usare la cache distribuita
Per usare l'interfaccia IDistributedCache , richiedere un'istanza di IDistributedCache nell'app. L'istanza viene fornita dall'inserimento delle dipendenze (DI).The instance is provided by dependency injection (DI).
All'avvio dell'app di esempio, IDistributedCache viene inserito in Program.cs
. L'ora corrente viene memorizzata nella cache usando IHostApplicationLifetime (per altre informazioni, vedere Host generico: IHostApplicationLifetime):
app.Lifetime.ApplicationStarted.Register(() =>
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = System.Text.Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(20));
app.Services.GetService<IDistributedCache>()
.Set("cachedTimeUTC", encodedCurrentTimeUTC, options);
});
L'app di esempio inserisce IDistributedCache nell'oggetto IndexModel
per l'uso dalla pagina Indice.
Ogni volta che viene caricata la pagina Indice, la cache viene verificata per il tempo memorizzato nella cache in OnGetAsync
. Se l'ora memorizzata nella cache non è scaduta, viene visualizzata l'ora. Se sono trascorsi 20 secondi dall'ultima volta che è stato eseguito l'accesso al tempo memorizzato nella cache (l'ultima volta che questa pagina è stata caricata), nella pagina viene visualizzato l'ora memorizzata nella cache scaduta.
Aggiornare immediatamente l'ora memorizzata nella cache all'ora corrente selezionando il pulsante Reimposta ora memorizzata nella cache. Il pulsante attiva il OnPostResetCachedTime
metodo del gestore.
public class IndexModel : PageModel
{
private readonly IDistributedCache _cache;
public IndexModel(IDistributedCache cache)
{
_cache = cache;
}
public string? CachedTimeUTC { get; set; }
public string? ASP_Environment { get; set; }
public async Task OnGetAsync()
{
CachedTimeUTC = "Cached Time Expired";
var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");
if (encodedCachedTimeUTC != null)
{
CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);
}
ASP_Environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
if (String.IsNullOrEmpty(ASP_Environment))
{
ASP_Environment = "Null, so Production";
}
}
public async Task<IActionResult> OnPostResetCachedTime()
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(20));
await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);
return RedirectToPage();
}
}
Non è necessario usare una durata singleton o con ambito per IDistributedCache le istanze con le implementazioni predefinite.
È anche possibile creare un'istanza IDistributedCache ovunque sia necessario anziché usare l'inserimento delle dipendenze, ma la creazione di un'istanza nel codice può rendere il codice più difficile da testare e violare il principio delle dipendenze esplicite.
Consigli
Quando decidi quale implementazione di IDistributedCache è migliore per la tua app, prendi in considerazione quanto segue:
- Infrastruttura esistente
- Requisiti per le prestazioni
- Costo
- Esperienza del team
Le soluzioni di memorizzazione nella cache si basano in genere sull'archiviazione in memoria per fornire un recupero rapido dei dati memorizzati nella cache, ma la memoria è una risorsa limitata e costosa da espandere. Archiviare solo i dati di uso comune in una cache.
Per la maggior parte delle app, una cache Redis offre una velocità effettiva più elevata e una latenza inferiore rispetto a una cache di SQL Server. Tuttavia, è consigliabile eseguire il benchmarking per determinare le caratteristiche delle prestazioni delle strategie di memorizzazione nella cache.
Quando SQL Server viene usato come archivio di backup della cache distribuita, l'uso dello stesso database per la cache e l'archiviazione e il recupero dei dati ordinari dell'app possono influire negativamente sulle prestazioni di entrambi. È consigliabile usare un'istanza di SQL Server dedicata per l'archivio di backup della cache distribuita.
Risorse aggiuntive
- Cache Redis in Azure
- database SQL in Azure
- ASP.NET Provider IDistributedCache core per NCache nelle Web farm (NCache su GitHub)
- File README del repository per Microsoft.Extensions.Caching.Cosmos
- Cache in memoria in ASP.NET Core
- Rilevare le modifiche con i token di modifica in ASP.NET Core
- Memorizzazione nella cache delle risposte in ASP.NET Core
- Middleware di memorizzazione nella cache delle risposte in ASP.NET Core
- Cache Tag Helper in ASP.NET Core MVC
- Helper tag cache distribuita in ASP.NET Core
- Ospitare ASP.NET Core in una web farm
Una cache distribuita è una cache condivisa da più server app, in genere gestita come servizio esterno ai server app che vi accedono. Una cache distribuita può migliorare le prestazioni e la scalabilità di un'app ASP.NET Core, soprattutto quando l'app è ospitata da un servizio cloud o da una server farm.
Una cache distribuita offre diversi vantaggi rispetto ad altri scenari di memorizzazione nella cache in cui i dati memorizzati nella cache vengono archiviati in singoli server app.
Quando i dati memorizzati nella cache vengono distribuiti, i dati:
- Coerente (coerente ) tra le richieste a più server.
- Sopravvive ai riavvii del server e alle distribuzioni di app.
- Non usa memoria locale.
La configurazione della cache distribuita è specifica dell'implementazione. Questo articolo descrive come configurare le cache distribuite di SQL Server e Redis. Sono disponibili anche implementazioni di terze parti, ad esempio NCache (NCache in GitHub). Indipendentemente dall'implementazione selezionata, l'app interagisce con la cache usando l'interfaccia IDistributedCache .
Visualizzare o scaricare il codice di esempio (procedura per il download)
Prerequisiti
Aggiungere un riferimento al pacchetto per il provider di cache distribuita usato:
Per una cache distribuita Redis, Microsoft.Extensions.Caching.StackExchangeRedis.
Per SQL Server, Microsoft.Extensions.Caching.SqlServer.
Per la cache distribuita NCache, NCache.Microsoft.Extensions.Caching.OpenSource.
-
Avviso
Questo articolo usa un database locale che non richiede l'autenticazione dell'utente. Le app di produzione devono usare il flusso di autenticazione più sicuro disponibile. Per altre informazioni sull'autenticazione per le app di test e produzione distribuite, vedere Proteggere i flussi di autenticazione.
Interfaccia IDistributedCache
L'interfaccia IDistributedCache fornisce i metodi seguenti per modificare gli elementi nell'implementazione della cache distribuita:
- Get, GetAsync: accetta una chiave stringa e recupera un elemento memorizzato nella cache come
byte[]
matrice, se presente nella cache. - Set, SetAsync: aggiunge un elemento (come
byte[]
matrice) alla cache usando una chiave stringa. - Refresh, RefreshAsync: aggiorna un elemento nella cache in base alla relativa chiave, reimpostando il timeout di scadenza scorrevole (se presente).
- Remove, RemoveAsync: rimuove un elemento della cache in base alla relativa chiave stringa.
Stabilire servizi di memorizzazione nella cache distribuita
Registrare un'implementazione di IDistributedCache in Program.cs
. Le implementazioni fornite dal framework descritte in questo argomento includono:
- Cache Redis distribuita
- Cache di memoria distribuita
- Cache di SQL Server distribuita
- Cache NCache distribuita
Cache Redis distribuita
È consigliabile che le app di produzione usino la cache Redis distribuita perché è la più efficiente. Per altre informazioni, vedere Raccomandazioni.
Redis è un archivio dati open source in memoria, che viene spesso usato come cache distribuita. È possibile configurare una Cache Redis di Azure per un'app ASP.NET Core ospitata in Azure e usare cache Redis di Azure per lo sviluppo locale.
Un'app configura l'implementazione della cache usando un'istanza RedisCache (AddStackExchangeRedisCache).
- Creare un cache di Azure per Redis.
- Copiare il stringa di connessione primario (StackExchange.Redis) in Configurazione.
- Sviluppo locale: salvare il stringa di connessione con Secret Manager.
- Azure: salvare i stringa di connessione in un archivio sicuro, ad esempio Azure Key Vault
Il codice seguente abilita il cache di Azure per Redis:
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("MyRedisConStr");
options.InstanceName = "SampleInstance";
});
Il codice precedente presuppone che il stringa di connessione primario (StackExchange.Redis) sia stato salvato nella configurazione con il nome MyRedisConStr
della chiave .
Per altre informazioni, vedere Azure Cache for Redis.
Vedere questo problema di GitHub per una discussione sugli approcci alternativi a una cache Redis locale.
Cache di memoria distribuita
La cache di memoria distribuita (AddDistributedMemoryCache) è un'implementazione fornita dal framework di IDistributedCache che archivia gli elementi in memoria. La cache di memoria distribuita non è una cache distribuita effettiva. Gli elementi memorizzati nella cache vengono archiviati dall'istanza dell'app nel server in cui è in esecuzione l'app.
La cache di memoria distribuita è un'implementazione utile:
- Negli scenari di sviluppo e test.
- Quando un singolo server viene usato nell'ambiente di produzione e nel consumo di memoria non è un problema. L'implementazione della cache di memoria distribuita astrae l'archiviazione dei dati memorizzata nella cache. Consente di implementare una vera soluzione di memorizzazione nella cache distribuita in futuro se sono necessari più nodi o tolleranza di errore.
L'app di esempio usa cache di memoria distribuita quando l'app viene eseguita nell'ambiente di sviluppo in Program.cs
:
builder.Services.AddDistributedMemoryCache();
Cache di SQL Server distribuita
L'implementazione della cache di SQL Server distribuita (AddDistributedSqlServerCache) consente alla cache distribuita di usare un database di SQL Server come archivio di backup. Per creare una tabella di elementi memorizzata nella cache di SQL Server in un'istanza di SQL Server, è possibile usare lo sql-cache
strumento . Lo strumento crea una tabella con il nome e lo schema specificati.
Creare una tabella in SQL Server eseguendo il sql-cache create
comando . Specificare l'istanza di SQL Server (Data Source
), il database (Initial Catalog
), lo schema (ad esempio, dbo
) e il nome della tabella (ad esempio, TestCache
):
dotnet sql-cache create "Data Source=(localdb)/MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache
Viene registrato un messaggio per indicare che lo strumento ha avuto esito positivo:
Table and index were created successfully.
La tabella creata dallo sql-cache
strumento ha lo schema seguente:
Nota
Un'app deve modificare i valori della cache usando un'istanza di IDistributedCache, non un oggetto SqlServerCache.
L'app di esempio implementa SqlServerCache in un ambiente non di sviluppo in Program.cs
:
builder.Services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString(
"DistCache_ConnectionString");
options.SchemaName = "dbo";
options.TableName = "TestCache";
});
Nota
Un ConnectionString oggetto (e facoltativamente SchemaName e TableName) viene in genere archiviato all'esterno del controllo del codice sorgente (ad esempio, archiviato da Secret Manager o nei appsettings.json
/appsettings.{Environment}.json
file). Il stringa di connessione può contenere credenziali che devono essere mantenute fuori dai sistemi di controllo del codice sorgente.
Cache NCache distribuita
NCache è una cache distribuita in memoria open source sviluppata in modo nativo in .NET e .NET Core. NCache funziona sia in locale che configurato come cluster di cache distribuita per un'app ASP.NET Core in esecuzione in Azure o in altre piattaforme di hosting.
Per installare e configurare NCache nel computer locale, vedere Guida introduttiva per Windows (.NET e .NET Core).
Per configurare NCache:
- Installare NuGet open source NCache.
- Configurare il cluster della cache in client.ncconf.
- Aggiungere il codice seguente a
Program.cs
:
builder.Services.AddNCacheDistributedCache(configuration =>
{
configuration.CacheName = "democache";
configuration.EnableLogs = true;
configuration.ExceptionsEnabled = true;
});
Usare la cache distribuita
Per usare l'interfaccia IDistributedCache , richiedere un'istanza di IDistributedCache nell'app. L'istanza viene fornita dall'inserimento delle dipendenze (DI).The instance is provided by dependency injection (DI).
All'avvio dell'app di esempio, IDistributedCache viene inserito in Program.cs
. L'ora corrente viene memorizzata nella cache usando IHostApplicationLifetime (per altre informazioni, vedere Host generico: IHostApplicationLifetime):
app.Lifetime.ApplicationStarted.Register(() =>
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = System.Text.Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(20));
app.Services.GetService<IDistributedCache>()
.Set("cachedTimeUTC", encodedCurrentTimeUTC, options);
});
L'app di esempio inserisce IDistributedCache nell'oggetto IndexModel
per l'uso dalla pagina Indice.
Ogni volta che viene caricata la pagina Indice, la cache viene verificata per il tempo memorizzato nella cache in OnGetAsync
. Se l'ora memorizzata nella cache non è scaduta, viene visualizzata l'ora. Se sono trascorsi 20 secondi dall'ultima volta che è stato eseguito l'accesso al tempo memorizzato nella cache (l'ultima volta che questa pagina è stata caricata), nella pagina viene visualizzato l'ora memorizzata nella cache scaduta.
Aggiornare immediatamente l'ora memorizzata nella cache all'ora corrente selezionando il pulsante Reimposta ora memorizzata nella cache. Il pulsante attiva il OnPostResetCachedTime
metodo del gestore.
public class IndexModel : PageModel
{
private readonly IDistributedCache _cache;
public IndexModel(IDistributedCache cache)
{
_cache = cache;
}
public string? CachedTimeUTC { get; set; }
public string? ASP_Environment { get; set; }
public async Task OnGetAsync()
{
CachedTimeUTC = "Cached Time Expired";
var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");
if (encodedCachedTimeUTC != null)
{
CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);
}
ASP_Environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
if (String.IsNullOrEmpty(ASP_Environment))
{
ASP_Environment = "Null, so Production";
}
}
public async Task<IActionResult> OnPostResetCachedTime()
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(20));
await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);
return RedirectToPage();
}
}
Non è necessario usare una durata singleton o con ambito per IDistributedCache le istanze con le implementazioni predefinite.
È anche possibile creare un'istanza IDistributedCache ovunque sia necessario anziché usare l'inserimento delle dipendenze, ma la creazione di un'istanza nel codice può rendere il codice più difficile da testare e violare il principio delle dipendenze esplicite.
Consigli
Quando decidi quale implementazione di IDistributedCache è migliore per la tua app, prendi in considerazione quanto segue:
- Infrastruttura esistente
- Requisiti per le prestazioni
- Costo
- Esperienza del team
Le soluzioni di memorizzazione nella cache si basano in genere sull'archiviazione in memoria per fornire un recupero rapido dei dati memorizzati nella cache, ma la memoria è una risorsa limitata e costosa da espandere. Archiviare solo i dati di uso comune in una cache.
Per la maggior parte delle app, una cache Redis offre una velocità effettiva più elevata e una latenza inferiore rispetto a una cache di SQL Server. Tuttavia, è consigliabile eseguire il benchmarking per determinare le caratteristiche delle prestazioni delle strategie di memorizzazione nella cache.
Quando SQL Server viene usato come archivio di backup della cache distribuita, l'uso dello stesso database per la cache e l'archiviazione e il recupero dei dati ordinari dell'app possono influire negativamente sulle prestazioni di entrambi. È consigliabile usare un'istanza di SQL Server dedicata per l'archivio di backup della cache distribuita.
Risorse aggiuntive
- Cache Redis in Azure
- database SQL in Azure
- ASP.NET Provider IDistributedCache core per NCache nelle Web farm (NCache su GitHub)
- Cache in memoria in ASP.NET Core
- Rilevare le modifiche con i token di modifica in ASP.NET Core
- Memorizzazione nella cache delle risposte in ASP.NET Core
- Middleware di memorizzazione nella cache delle risposte in ASP.NET Core
- Cache Tag Helper in ASP.NET Core MVC
- Helper tag cache distribuita in ASP.NET Core
- Ospitare ASP.NET Core in una web farm
Una cache distribuita è una cache condivisa da più server app, in genere gestita come servizio esterno ai server app che vi accedono. Una cache distribuita può migliorare le prestazioni e la scalabilità di un'app ASP.NET Core, soprattutto quando l'app è ospitata da un servizio cloud o da una server farm.
Una cache distribuita offre diversi vantaggi rispetto ad altri scenari di memorizzazione nella cache in cui i dati memorizzati nella cache vengono archiviati in singoli server app.
Quando i dati memorizzati nella cache vengono distribuiti, i dati:
- Coerente (coerente ) tra le richieste a più server.
- Sopravvive ai riavvii del server e alle distribuzioni di app.
- Non usa memoria locale.
La configurazione della cache distribuita è specifica dell'implementazione. Questo articolo descrive come configurare le cache distribuite di SQL Server e Redis. Sono disponibili anche implementazioni di terze parti, ad esempio NCache (NCache in GitHub). Indipendentemente dall'implementazione selezionata, l'app interagisce con la cache usando l'interfaccia IDistributedCache .
Visualizzare o scaricare il codice di esempio (procedura per il download)
Prerequisiti
Per usare una cache distribuita di SQL Server, aggiungere un riferimento al pacchetto Microsoft.Extensions.Caching.SqlServer .
Per usare una cache distribuita Redis, aggiungere un riferimento al pacchetto Microsoft.Extensions.Caching.StackExchangeRedis .
Per usare la cache distribuita NCache, aggiungere un riferimento al pacchetto NCache.Microsoft.Extensions.Caching.OpenSource .
Interfaccia IDistributedCache
L'interfaccia IDistributedCache fornisce i metodi seguenti per modificare gli elementi nell'implementazione della cache distribuita:
- Get, GetAsync: accetta una chiave stringa e recupera un elemento memorizzato nella cache come
byte[]
matrice, se presente nella cache. - Set, SetAsync: aggiunge un elemento (come
byte[]
matrice) alla cache usando una chiave stringa. - Refresh, RefreshAsync: aggiorna un elemento nella cache in base alla relativa chiave, reimpostando il timeout di scadenza scorrevole (se presente).
- Remove, RemoveAsync: rimuove un elemento della cache in base alla relativa chiave stringa.
Stabilire servizi di memorizzazione nella cache distribuita
Registrare un'implementazione di IDistributedCache in Startup.ConfigureServices
. Le implementazioni fornite dal framework descritte in questo argomento includono:
- Cache di memoria distribuita
- Cache di SQL Server distribuita
- Cache Redis distribuita
- Cache NCache distribuita
Cache di memoria distribuita
La cache di memoria distribuita (AddDistributedMemoryCache) è un'implementazione fornita dal framework di IDistributedCache che archivia gli elementi in memoria. La cache di memoria distribuita non è una cache distribuita effettiva. Gli elementi memorizzati nella cache vengono archiviati dall'istanza dell'app nel server in cui è in esecuzione l'app.
La cache di memoria distribuita è un'implementazione utile:
- Negli scenari di sviluppo e test.
- Quando un singolo server viene usato nell'ambiente di produzione e nel consumo di memoria non è un problema. L'implementazione della cache di memoria distribuita astrae l'archiviazione dei dati memorizzata nella cache. Consente di implementare una vera soluzione di memorizzazione nella cache distribuita in futuro se sono necessari più nodi o tolleranza di errore.
L'app di esempio usa cache di memoria distribuita quando l'app viene eseguita nell'ambiente di sviluppo in Startup.ConfigureServices
:
services.AddDistributedMemoryCache();
Cache di SQL Server distribuita
L'implementazione della cache di SQL Server distribuita (AddDistributedSqlServerCache) consente alla cache distribuita di usare un database di SQL Server come archivio di backup. Per creare una tabella di elementi memorizzata nella cache di SQL Server in un'istanza di SQL Server, è possibile usare lo sql-cache
strumento . Lo strumento crea una tabella con il nome e lo schema specificati.
Creare una tabella in SQL Server eseguendo il sql-cache create
comando . Specificare l'istanza di SQL Server (Data Source
), il database (Initial Catalog
), lo schema (ad esempio, dbo
) e il nome della tabella (ad esempio, TestCache
):
dotnet sql-cache create "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache
Viene registrato un messaggio per indicare che lo strumento ha avuto esito positivo:
Table and index were created successfully.
La tabella creata dallo sql-cache
strumento ha lo schema seguente:
Nota
Un'app deve modificare i valori della cache usando un'istanza di IDistributedCache, non un oggetto SqlServerCache.
L'app di esempio implementa SqlServerCache in un ambiente non di sviluppo in Startup.ConfigureServices
:
services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString =
_config["DistCache_ConnectionString"];
options.SchemaName = "dbo";
options.TableName = "TestCache";
});
Nota
Un ConnectionString oggetto (e facoltativamente SchemaName e TableName) viene in genere archiviato all'esterno del controllo del codice sorgente (ad esempio, archiviato da Secret Manager o nei appsettings.json
/appsettings.{Environment}.json
file). Il stringa di connessione può contenere credenziali che devono essere mantenute fuori dai sistemi di controllo del codice sorgente.
Cache Redis distribuita
Redis è un archivio dati open source in memoria, che viene spesso usato come cache distribuita. È possibile configurare una Cache Redis di Azure per un'app ASP.NET Core ospitata in Azure e usare cache Redis di Azure per lo sviluppo locale.
Un'app configura l'implementazione della cache usando un'istanza RedisCache (AddStackExchangeRedisCache).
- Creare un cache di Azure per Redis.
- Copiare il stringa di connessione primario (StackExchange.Redis) in Configurazione.
- Sviluppo locale: salvare il stringa di connessione con Secret Manager.
- Azure: salvare i stringa di connessione in un archivio sicuro, ad esempio Azure Key Vault
Il codice seguente abilita il cache di Azure per Redis:
public void ConfigureServices(IServiceCollection services)
{
if (_hostContext.IsDevelopment())
{
services.AddDistributedMemoryCache();
}
else
{
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = _config["MyRedisConStr"];
options.InstanceName = "SampleInstance";
});
}
services.AddRazorPages();
}
Il codice precedente presuppone che il stringa di connessione primario (StackExchange.Redis) sia stato salvato nella configurazione con il nome MyRedisConStr
della chiave .
Per altre informazioni, vedere Azure Cache for Redis.
Vedere questo problema di GitHub per una discussione sugli approcci alternativi a una cache Redis locale.
Cache NCache distribuita
NCache è una cache distribuita in memoria open source sviluppata in modo nativo in .NET e .NET Core. NCache funziona sia in locale che configurato come cluster di cache distribuita per un'app ASP.NET Core in esecuzione in Azure o in altre piattaforme di hosting.
Per installare e configurare NCache nel computer locale, vedere Guida introduttiva per Windows (.NET e .NET Core).
Per configurare NCache:
Installare NuGet open source NCache.
Configurare il cluster della cache in client.ncconf.
Aggiungere il codice seguente a
Startup.ConfigureServices
:services.AddNCacheDistributedCache(configuration => { configuration.CacheName = "demoClusteredCache"; configuration.EnableLogs = true; configuration.ExceptionsEnabled = true; });
Usare la cache distribuita
Per usare l'interfaccia, richiedere un'istanza IDistributedCache di IDistributedCache da qualsiasi costruttore nell'app. L'istanza viene fornita dall'inserimento delle dipendenze (DI).The instance is provided by dependency injection (DI).
All'avvio dell'app di esempio, IDistributedCache viene inserito in Startup.Configure
. L'ora corrente viene memorizzata nella cache usando IHostApplicationLifetime (per altre informazioni, vedere Host generico: IHostApplicationLifetime):
public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
IHostApplicationLifetime lifetime, IDistributedCache cache)
{
lifetime.ApplicationStarted.Register(() =>
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(20));
cache.Set("cachedTimeUTC", encodedCurrentTimeUTC, options);
});
L'app di esempio inserisce IDistributedCache nell'oggetto IndexModel
per l'uso dalla pagina Indice.
Ogni volta che viene caricata la pagina Indice, la cache viene verificata per il tempo memorizzato nella cache in OnGetAsync
. Se l'ora memorizzata nella cache non è scaduta, viene visualizzata l'ora. Se sono trascorsi 20 secondi dall'ultima volta che è stato eseguito l'accesso al tempo memorizzato nella cache (l'ultima volta che questa pagina è stata caricata), nella pagina viene visualizzato l'ora memorizzata nella cache scaduta.
Aggiornare immediatamente l'ora memorizzata nella cache all'ora corrente selezionando il pulsante Reimposta ora memorizzata nella cache. Il pulsante attiva il OnPostResetCachedTime
metodo del gestore.
public class IndexModel : PageModel
{
private readonly IDistributedCache _cache;
public IndexModel(IDistributedCache cache)
{
_cache = cache;
}
public string CachedTimeUTC { get; set; }
public async Task OnGetAsync()
{
CachedTimeUTC = "Cached Time Expired";
var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");
if (encodedCachedTimeUTC != null)
{
CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);
}
}
public async Task<IActionResult> OnPostResetCachedTime()
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(20));
await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);
return RedirectToPage();
}
}
Nota
Non è necessario usare una durata singleton o con ambito per IDistributedCache le istanze (almeno per le implementazioni predefinite).
È anche possibile creare un'istanza IDistributedCache ovunque sia necessario anziché usare l'inserimento delle dipendenze, ma la creazione di un'istanza nel codice può rendere il codice più difficile da testare e violare il principio delle dipendenze esplicite.
Consigli
Quando decidi quale implementazione di IDistributedCache è migliore per la tua app, prendi in considerazione quanto segue:
- Infrastruttura esistente
- Requisiti per le prestazioni
- Costo
- Esperienza del team
Le soluzioni di memorizzazione nella cache si basano in genere sull'archiviazione in memoria per fornire un recupero rapido dei dati memorizzati nella cache, ma la memoria è una risorsa limitata e costosa da espandere. Archiviare solo i dati di uso comune in una cache.
In genere, una cache Redis offre una velocità effettiva più elevata e una latenza inferiore rispetto a una cache di SQL Server. Tuttavia, il benchmarking è in genere necessario per determinare le caratteristiche delle prestazioni delle strategie di memorizzazione nella cache.
Quando SQL Server viene usato come archivio di backup della cache distribuita, l'uso dello stesso database per la cache e l'archiviazione e il recupero dei dati ordinari dell'app possono influire negativamente sulle prestazioni di entrambi. È consigliabile usare un'istanza di SQL Server dedicata per l'archivio di backup della cache distribuita.
Risorse aggiuntive
- Cache Redis in Azure
- database SQL in Azure
- ASP.NET Provider IDistributedCache core per NCache nelle Web farm (NCache su GitHub)
- Cache in memoria in ASP.NET Core
- Rilevare le modifiche con i token di modifica in ASP.NET Core
- Memorizzazione nella cache delle risposte in ASP.NET Core
- Middleware di memorizzazione nella cache delle risposte in ASP.NET Core
- Cache Tag Helper in ASP.NET Core MVC
- Helper tag cache distribuita in ASP.NET Core
- Ospitare ASP.NET Core in una web farm