Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Di Mohsin Nasir e smandia
Note
Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 10 di questo articolo.
Warning
Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere i criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 10 di questo articolo.
Una cache distribuita è una cache condivisa da più server app. La cache viene in genere mantenuta come servizio esterno per i server app che vi accedono. Una cache distribuita può migliorare le prestazioni e la scalabilità di un'app ASP.NET Core, soprattutto quando un servizio cloud o una server farm ospita l'app.
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:
- Il sistema è coerente (consistente) 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, Redis o Postgres. Sono disponibili anche implementazioni non Microsoft, ad esempio NCache (NCache in GitHub), Azure Cosmos DB e Postgres. 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)
Warning
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.
Prerequisites
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 Postgres, Microsoft.Extensions.Caching.Postgres.
- Per Azure Cosmos DB, Microsoft.Extensions.Caching.Cosmos.
- Per la cache distribuita NCache, NCache.Microsoft.Extensions.Caching.OpenSource.
Usare l'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 nel file Program.cs . Le implementazioni fornite dal framework seguenti sono descritte in questo articolo:
- Cache Redis distribuita
- Cache di memoria distribuita
- Cache di SQL Server distribuita
- Cache Postgres distribuita
- Cache distribuita di NCache
- Cache di Azure Cosmos DB distribuita
Cache Redis distribuita
La cache Redis distribuita offre prestazioni ottimali ed è consigliata per le app di produzione. 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. Per altre informazioni, vedere Esaminare le raccomandazioni della cache.
Un'app configura l'implementazione della cache con un'istanza RedisCache chiamando il AddStackExchangeRedisCache metodo . Per la memorizzazione nella cache dell'output, usare il metodo AddStackExchangeRedisOutputCache.
Creare un'istanza di cache di Azure per Redis.
Copiare la stringa di connessione primaria (StackExchange.Redis) in Configuration.
Per lo sviluppo locale: salvare il stringa di connessione con Secret Manager.
For Azure: salvare il 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 sopra presuppone che la stringa di connessione primaria (StackExchange.Redis) sia salvata nella configurazione con il nome della chiave MyRedisConStr.
Per altre informazioni, vedere Azure Managed Redis.
Per una discussione sugli approcci alternativi a una cache Redis locale, vedere GitHub problema /dotnet/aspnetcore #19542.
Cache di memoria distribuita
La cache di memoria distribuita (AddDistributedMemoryCache) è un'implementazione fornita dal framework di IDistributedCache che archivia gli elementi in memoria. Tuttavia, la cache di memoria distribuita non è una cache distribuita effettiva. L'istanza dell'app archivia gli elementi memorizzati nella cache nel server in cui è in esecuzione l'app.
La cache di memoria distribuita è un'implementazione utile per scenari di sviluppo e test. È utile anche per un singolo server in uno scenario di produzione in cui l'utilizzo della 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 la cache di memoria distribuita quando l'app viene eseguita nell'ambiente Development nel file Program.cs .
builder.Services.AddDistributedMemoryCache();
Cache SQL Server distribuita
L'implementazione della cache SQL Server distribuita (AddDistributedSqlServerCache) consente alla cache distribuita di usare un database 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
Quando lo strumento ha esito positivo, viene registrato un messaggio:
Table and index were created successfully.
La tabella creata dallo sql-cache strumento ha lo schema seguente:
Note
Un'app deve modificare i valori della cache usando un'istanza di IDistributedCache, non un'istanza di SqlServerCache.
L'app di esempio implementa la SqlServerCache classe in un ambiente non di sviluppo (Development) nel file Program.cs :
builder.Services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString(
"DistCache_ConnectionString");
options.SchemaName = "dbo";
options.TableName = "TestCache";
});
Note
Le proprietà come ConnectionString (e facoltativamente SchemaName , e TableName) vengono in genere archiviate all'esterno del controllo del codice sorgente. Ad esempio, Secret Manager o ilappsettings.json o appsettings.{ Environment}.json file potrebbe archiviare le proprietà. Il stringa di connessione può contenere credenziali che devono essere mantenute fuori dai sistemi di controllo del codice sorgente.
Per altre informazioni, vedere database SQL in Azure.
Cache Postgres distribuita
Database di Azure per PostgreSQL può essere usato come archivio di backup della cache distribuita tramite l'interfaccia IDistributedCache . Database di Azure per PostgreSQL è un'offerta DBaaS (Database as a Service) completamente gestita e pronta per l'intelligenza artificiale basata sul motore PostgreSQL open source. La progettazione supporta carichi di lavoro cruciali con prestazioni prevedibili, sicurezza affidabile, disponibilità elevata e scalabilità senza problemi.
Dopo aver installato il pacchetto NuGet Microsoft.Extensions.Caching.Postgres , configurare la cache distribuita come segue:
Registrare il servizio.
using Microsoft.Extensions.DependencyInjection; var builder = WebApplication.CreateBuilder(args); // Register the Postgres distributed cache. builder.Services.AddDistributedPostgresCache(options => { options.ConnectionString = builder.Configuration.GetConnectionString("PostgresCache"); options.SchemaName = builder.Configuration.GetValue<string>("PostgresCache:SchemaName", "public"); options.TableName = builder.Configuration.GetValue<string>("PostgresCache:TableName", "cache"); options.CreateIfNotExists = builder.Configuration.GetValue<bool>("PostgresCache:CreateIfNotExists", true); options.UseWAL = builder.Configuration.GetValue<bool>("PostgresCache:UseWAL", false); // Optional: Configure expiration settings. var expirationInterval = builder.Configuration.GetValue<string>("PostgresCache:ExpiredItemsDeletionInterval"); if (!string.IsNullOrEmpty(expirationInterval) && TimeSpan.TryParse(expirationInterval, out var interval)) { options.ExpiredItemsDeletionInterval = interval; } var slidingExpiration = builder.Configuration.GetValue<string>("PostgresCache:DefaultSlidingExpiration"); if (!string.IsNullOrEmpty(slidingExpiration) && TimeSpan.TryParse(slidingExpiration, out var sliding)) { options.DefaultSlidingExpiration = sliding; } }); var app = builder.Build();Usare la cache.
public class MyService { private readonly IDistributedCache _cache; public MyService(IDistributedCache cache) { _cache = cache; } public async Task<string> GetDataAsync(string key) { var cachedData = await _cache.GetStringAsync(key); if (cachedData == null) { // Fetch the data from source. var data = await FetchDataFromSource(); // Cache the data with options. var options = new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30), SlidingExpiration = TimeSpan.FromMinutes(5) }; await _cache.SetStringAsync(key, data, options); return data; } return cachedData; } }
Cache NCache distribuita
NCache è una cache distribuita in memoria open source sviluppata in modo nativo in .NET. 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 la Guida introduttiva.
Per configurare NCache:
Installare il pacchetto NuGet NCache SDK, che supporta NCache Opensource per .NET Framework e .NET app Core.
Configurare il cluster della cache nella configurazione del client (nel file client.ncconf).
Aggiungere il codice seguente al file Program.cs :
builder.Services.AddNCacheDistributedCache(configuration =>
{
configuration.CacheName = "democache";
configuration.EnableLogs = true;
configuration.ExceptionsEnabled = true;
});
Cache Azure Cosmos DB distribuita
Azure Cosmos DB può essere configurato in ASP.NET Core come provider di stato 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 Microsoft. Extensions.Caching.Cosmos pacchetto NuGet, configurare una cache distribuita Azure Cosmos DB. È possibile usare un client Azure Cosmos DB esistente o crearne uno nuovo, come descritto nelle sezioni seguenti.
Per altre informazioni, vedere l'estensione Microsoft caching usando Azure Cosmos DB, il file README del repository GitHub per il pacchetto NuGet.
Riutilizzare un client esistente
Il modo più semplice per configurare una cache distribuita consiste nel riutilizzare un client di Azure Cosmos DB esistente. In questo caso, l'istanza CosmosClient non viene 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 viene 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 è fornita da dependency injection (DI).
All'avvio dell'app di esempio, l'istanza IDistributedCache viene inserita nel file Program.cs . L'ora corrente viene memorizzata nella cache tramite l'interfaccia IHostApplicationLifetime . Per altre informazioni, vedere .NET 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 l'istanza IDistributedCache nell'oggetto IndexModel da usare dalla pagina Index.
Ogni volta che viene caricata la pagina Indice, la cache viene verificata per il tempo memorizzato nella cache usando il OnGetAsync metodo . 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 alla cache (l'ultima volta che questa pagina è stata caricata), nella pagina viene visualizzato il messaggio Ora memorizzata nella cache scaduta.
Aggiornare immediatamente l'ora memorizzata nella cache all'ora corrente selezionando l'opzione Reimposta ora memorizzata nella cache . Questa azione 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();
}
}
Note
Non è necessario usare una durata singleton o con ambito per le istanze IDistributedCache con un'implementazione predefinita.
È anche possibile creare un'istanza IDistributedCache ovunque possa servire, invece di utilizzare l'inserimento delle dipendenze. Tuttavia, la creazione di un'istanza nel codice può rendere il codice più difficile da testare e violare il principio delle dipendenze esplicite.
Revisione delle raccomandazioni della cache
Quando decidi quale implementazione dell'interfaccia è migliore per la IDistributedCache tua app, prendi in considerazione i punti seguenti:
- Infrastruttura esistente
- Requisiti di prestazioni
- Cost
- 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.
Se SQL Server è l'archivio di backup della cache distribuita e la cache e l'archiviazione/recupero dei dati dell'app usano lo stesso database, le prestazioni possono essere ridotte. L'approccio consigliato consiste nell'usare un'istanza di SQL Server dedicata per l'archivio di backup della cache distribuita.
Contenuti correlati
- Cache Redis in Azure
- SQL Database su Azure
- Database di Azure per PostgreSQL
- Provider IDistributedCache di ASP.NET Core per NCache nelle server farm (NCache su GitHub)
- File README del repository per Microsoft.Extensions.Caching.Cosmos
- Rilevare le modifiche con i token di modifica in ASP.NET Core
- Tag Helper Cache in ASP.NET Core MVC
- Tag Helper per 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:
- Il sistema è coerente (consistente) 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, Redis e Postgres. 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)
Prerequisites
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 Postgres, Microsoft.Extensions.Caching.Postgres.
Per la cache distribuita NCache, NCache.Microsoft.Extensions.Caching.OpenSource.
-
Warning
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 Postgres 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 la stringa di connessione primaria (StackExchange.Redis) in Configurazione.
- Sviluppo locale: Salva la 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 la stringa di connessione primaria (StackExchange.Redis) sia stata salvata nella configurazione con il nome della chiave MyRedisConStr.
Per altre informazioni, vedere cache di Azure per 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 Development 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:
Note
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 nonDevelopment in Program.cs:
builder.Services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString(
"DistCache_ConnectionString");
options.SchemaName = "dbo";
options.TableName = "TestCache";
});
Note
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 Postgres distribuita
Database di Azure per PostgreSQL può essere usato come archivio di backup della cache distribuita tramite l'interfaccia IDistributedCache . Database di Azure per PostgreSQL è un'offerta di Database as a Service (DBaaS) completamente gestita e pronta per l'intelligenza artificiale basata sul motore PostgreSQL open source, progettata per supportare carichi di lavoro cruciali con prestazioni prevedibili, sicurezza affidabile, disponibilità elevata e scalabilità senza problemi.
Dopo aver installato il pacchetto NuGet Microsoft.Extensions.Caching.Postgres , configurare la cache distribuita come segue:
- Registrare il servizio
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Register Postgres distributed cache
builder.Services.AddDistributedPostgresCache(options => {
options.ConnectionString = builder.Configuration.GetConnectionString("PostgresCache");
options.SchemaName = builder.Configuration.GetValue<string>("PostgresCache:SchemaName", "public");
options.TableName = builder.Configuration.GetValue<string>("PostgresCache:TableName", "cache");
options.CreateIfNotExists = builder.Configuration.GetValue<bool>("PostgresCache:CreateIfNotExists", true);
options.UseWAL = builder.Configuration.GetValue<bool>("PostgresCache:UseWAL", false);
// Optional: Configure expiration settings
var expirationInterval = builder.Configuration.GetValue<string>("PostgresCache:ExpiredItemsDeletionInterval");
if (!string.IsNullOrEmpty(expirationInterval) && TimeSpan.TryParse(expirationInterval, out var interval)) {
options.ExpiredItemsDeletionInterval = interval;
}
var slidingExpiration = builder.Configuration.GetValue<string>("PostgresCache:DefaultSlidingExpiration");
if (!string.IsNullOrEmpty(slidingExpiration) && TimeSpan.TryParse(slidingExpiration, out var sliding)) {
options.DefaultSlidingExpiration = sliding;
}
});
var app = builder.Build();
- Usare la cache
public class MyService {
private readonly IDistributedCache _cache;
public MyService(IDistributedCache cache) {
_cache = cache;
}
public async Task<string> GetDataAsync(string key) {
var cachedData = await _cache.GetStringAsync(key);
if (cachedData == null) {
// Fetch data from source
var data = await FetchDataFromSource();
// Cache the data with options
var options = new DistributedCacheEntryOptions {
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30),
SlidingExpiration = TimeSpan.FromMinutes(5)
};
await _cache.SetStringAsync(key, data, options);
return data;
}
return cachedData;
}
}
Cache distribuita NCache
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 NCache open source NuGet.
- 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'iniezione delle dipendenze (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 controllata per verificare il tempo salvato 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 una durata con ambito limitato per le IDistributedCache istanze con le implementazioni predefinite.
È anche possibile creare un'istanza IDistributedCache ovunque sia necessario anziché usare l'Inversione 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.
Recommendations
Quando decidi quale implementazione di IDistributedCache è migliore per la tua app, prendi in considerazione quanto segue:
- Infrastruttura esistente
- Requisiti di prestazioni
- Cost
- 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
- Redis Cache su Azure
- SQL Database su Azure
- Database di Azure per PostgreSQL
- Provider IDistributedCache di ASP.NET Core per NCache nelle farm Web (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 caching delle risposte in ASP.NET Core
- Tag Helper Cache in ASP.NET Core MVC
- Tag Helper per 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:
- Il sistema è coerente (consistente) 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, Redis e Postgres. 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)
Prerequisites
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 una cache distribuita postgres, aggiungere un riferimento al pacchetto Microsoft.Extensions.Caching.Postgres .
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 Postgres 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 Development 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:
Note
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 nonDevelopment in Startup.ConfigureServices:
services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString =
_config["DistCache_ConnectionString"];
options.SchemaName = "dbo";
options.TableName = "TestCache";
});
Note
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 la stringa di connessione primaria (StackExchange.Redis) in Configurazione.
- Sviluppo locale: Salva la 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 la stringa di connessione primaria (StackExchange.Redis) sia stata salvata nella configurazione con il nome della chiave MyRedisConStr.
Per altre informazioni, vedere cache di Azure per Redis.
Vedere questo problema di GitHub per una discussione sugli approcci alternativi a una cache Redis locale.
Cache Postgres distribuita
Database di Azure per PostgreSQL può essere usato come archivio di backup della cache distribuita tramite l'interfaccia IDistributedCache . Database di Azure per PostgreSQL è un'offerta di Database as a Service (DBaaS) completamente gestita e pronta per l'intelligenza artificiale basata sul motore PostgreSQL open source, progettata per supportare carichi di lavoro cruciali con prestazioni prevedibili, sicurezza affidabile, disponibilità elevata e scalabilità senza problemi.
Dopo aver installato il pacchetto NuGet Microsoft.Extensions.Caching.Postgres , configurare la cache distribuita come segue:
- Registrare il servizio
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Register Postgres distributed cache
builder.Services.AddDistributedPostgresCache(options => {
options.ConnectionString = builder.Configuration.GetConnectionString("PostgresCache");
options.SchemaName = builder.Configuration.GetValue<string>("PostgresCache:SchemaName", "public");
options.TableName = builder.Configuration.GetValue<string>("PostgresCache:TableName", "cache");
options.CreateIfNotExists = builder.Configuration.GetValue<bool>("PostgresCache:CreateIfNotExists", true);
options.UseWAL = builder.Configuration.GetValue<bool>("PostgresCache:UseWAL", false);
// Optional: Configure expiration settings
var expirationInterval = builder.Configuration.GetValue<string>("PostgresCache:ExpiredItemsDeletionInterval");
if (!string.IsNullOrEmpty(expirationInterval) && TimeSpan.TryParse(expirationInterval, out var interval)) {
options.ExpiredItemsDeletionInterval = interval;
}
var slidingExpiration = builder.Configuration.GetValue<string>("PostgresCache:DefaultSlidingExpiration");
if (!string.IsNullOrEmpty(slidingExpiration) && TimeSpan.TryParse(slidingExpiration, out var sliding)) {
options.DefaultSlidingExpiration = sliding;
}
});
var app = builder.Build();
- Usare la cache
public class MyService {
private readonly IDistributedCache _cache;
public MyService(IDistributedCache cache) {
_cache = cache;
}
public async Task<string> GetDataAsync(string key) {
var cachedData = await _cache.GetStringAsync(key);
if (cachedData == null) {
// Fetch data from source
var data = await FetchDataFromSource();
// Cache the data with options
var options = new DistributedCacheEntryOptions {
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30),
SlidingExpiration = TimeSpan.FromMinutes(5)
};
await _cache.SetStringAsync(key, data, options);
return data;
}
return cachedData;
}
}
Cache distribuita NCache
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 il pacchetto NuGet open source di 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 IDistributedCache, richiedere un'istanza di IDistributedCache da qualsiasi costruttore nell'app. L'istanza viene fornita dall'iniezione delle dipendenze (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();
}
}
Note
Non è necessario usare una durata singleton o con ambito per le istanze di IDistributedCache (almeno per le implementazioni predefinite).
È anche possibile creare un'istanza di IDistributedCache ovunque sia necessario anziché usare DI (Dependency Injection), ma la creazione di un'istanza nel codice può rendere il codice più difficile da testare e viola il principio delle dipendenze esplicite.
Recommendations
Quando decidi quale implementazione di IDistributedCache è migliore per la tua app, prendi in considerazione quanto segue:
- Infrastruttura esistente
- Requisiti di prestazioni
- Cost
- 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 di Redis su Azure
- Database SQL su Azure
- Database di Azure per PostgreSQL
- Provider IDistributedCache di ASP.NET Core per NCache nelle server 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 Cache di Risposta in ASP.NET Core
- Tag Helper Cache in ASP.NET Core MVC
- Tag Helper per cache distribuita in ASP.NET Core
- Ospitare ASP.NET Core in una web farm