Gedistribueerde caching in ASP.NET Core

Door Mohsin Nasir en smandia

Note

Dit is niet de nieuwste versie van dit artikel. Zie de .NET 10-versie van dit artikel voor de huidige release.

Warning

Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie het .NET- en .NET Core-ondersteuningsbeleid voor meer informatie. Zie de .NET 10-versie van dit artikel voor de huidige release.

Een gedistribueerde cache is een cache die wordt gedeeld door meerdere app-servers. De cache wordt doorgaans onderhouden als een externe service voor de app-servers die er toegang toe hebben. Een gedistribueerde cache kan de prestaties en schaalbaarheid van een ASP.NET Core-app verbeteren, met name wanneer een cloudservice of een serverfarm als host fungeert voor de app.

Een gedistribueerde cache heeft verschillende voordelen ten opzichte van andere cachescenario's waarbij gegevens in de cache worden opgeslagen op afzonderlijke app-servers.

Wanneer gegevens in de cache worden gedistribueerd, worden de gegevens als volgt verdeeld:

  • Is coherent (consistent) tussen aanvragen naar meerdere servers.
  • Overleeft het opnieuw opstarten van de server en app-implementaties.
  • Gebruikt geen lokaal geheugen.

Configuratie van gedistribueerde cache is implementatiespecifiek. In dit artikel wordt beschreven hoe u gedistribueerde SQL Server-, Redis- of Postgres-caches configureert. Er zijn ook niet-Microsoft implementaties beschikbaar, zoals NCache (NCache op GitHub), Azure Cosmos DB en Postgres. Ongeacht welke implementatie is geselecteerd, communiceert de app met de cache met behulp van de IDistributedCache interface.

Voorbeeldcode bekijken of downloaden (hoe download je)

Warning

In dit artikel wordt een lokale database gebruikt waarvoor de gebruiker niet hoeft te worden geverifieerd. Productie-apps moeten gebruikmaken van de veiligste verificatiestroom die beschikbaar is. Zie Beveiligde verificatiestromenvoor meer informatie over verificatie voor geïmplementeerde test- en productie-apps.

Prerequisites

Voeg een pakketverwijzing toe voor de gedistribueerde cacheprovider die wordt gebruikt:

De IDistributedCache-interface gebruiken

De IDistributedCache interface biedt de volgende methoden voor het bewerken van items in de implementatie van de gedistribueerde cache:

  • Get, : GetAsyncAccepteert een tekenreekssleutel en haalt een item in de cache op als een byte[] matrix als deze in de cache wordt gevonden.
  • Set, SetAsync: Voegt een item (als byte[] array) toe aan de cache met behulp van een tekenreekssleutel.
  • Refresh, RefreshAsync: Hiermee vernieuwt u een item in de cache op basis van de sleutel en stelt u de time-out voor verschuivende verlooptijd opnieuw in (indien van toepassing).
  • Remove, : RemoveAsyncVerwijdert een cache-item op basis van de tekenreekssleutel.

Gedistribueerde cachingservices instellen

Registreer een implementatie van IDistributedCache in het Program.cs-bestand. De volgende framework-implementaties worden beschreven in dit artikel:

Gedistribueerde Redis-cache

De gedistribueerde Redis-cache levert de beste prestaties en wordt aanbevolen voor productie-apps. Redis is een opensource-gegevensarchief in het geheugen, dat vaak wordt gebruikt als een gedistribueerde cache. U kunt een Azure Cache voor Redis configureren voor een door Azure gehoste ASP.NET Core-app en een Azure Cache voor Redis gebruiken voor lokale ontwikkeling. Zie cache-aanbevelingen beoordelen voor meer informatie.

Een app configureert de cacheimplementatie met een RedisCache exemplaar door de AddStackExchangeRedisCache methode aan te roepen. Gebruik de methode voor AddStackExchangeRedisOutputCache.

  1. Maak een exemplaar van Azure Cache voor Redis.

  2. Kopieer de primaire verbindingsreeks (StackExchange.Redis) naar Configuratie.

    • Voor lokale ontwikkeling: Sla de verbindingsreeks op met Secret Manager.

    • Voor Azure: Sla de verbindingsreeks op in een beveiligd archief, zoals Azure Key Vault.

Met de volgende code wordt Azure Cache voor Redis ingeschakeld:

builder.Services.AddStackExchangeRedisCache(options =>
 {
     options.Configuration = builder.Configuration.GetConnectionString("MyRedisConStr");
     options.InstanceName = "SampleInstance";
 });

In de voorgaande code wordt ervan uitgegaan dat de primaire verbindingsreeks (StackExchange.Redis) wordt opgeslagen in de configuratie met de sleutelnaam MyRedisConStr.

Zie Azure Managed Redis voor meer informatie.

Zie GitHub /dotnet/aspnetcore issue #19542 voor een discussie over alternatieve benaderingen van een lokale Redis-cache.

Gedistribueerde geheugencache

De gedistribueerde geheugencache (AddDistributedMemoryCache) is een framework-implementatie van IDistributedCache die items in het geheugen opslaat. De gedistribueerde geheugencache is echter geen werkelijke gedistribueerde cache. In het app-exemplaar worden de items in de cache opgeslagen op de server waarop de app wordt uitgevoerd.

De gedistribueerde geheugencache is een nuttige implementatie voor ontwikkelings- en testscenario's. Het is ook handig voor één server in een productiescenario waarbij het geheugenverbruik geen probleem is. Door de gedistribueerde geheugencache te implementeren, wordt gegevensopslag in de cache geabstraheerd. Hiermee kunt u in de toekomst een echte oplossing voor gedistribueerde caching implementeren als meerdere knooppunten of fouttolerantie nodig zijn.

De voorbeeld-app maakt gebruik van de gedistribueerde geheugencache wanneer de app wordt uitgevoerd in de Development omgeving in het Program.cs-bestand .

builder.Services.AddDistributedMemoryCache();

Gedistribueerde SQL Server-cache

Met de gedistribueerde SQL Server cache-implementatie (AddDistributedSqlServerCache) kan de gedistribueerde cache een SQL Server-database gebruiken als back-uparchief. Als u een sql Server-itemtabel in de cache wilt maken in een SQL Server-exemplaar, kunt u het sql-cache hulpprogramma gebruiken. Met het hulpprogramma maakt u een tabel met de naam en het schema dat u opgeeft.

Maak een tabel in SQL Server door de opdracht uit te sql-cache create voeren. Geef het SQL Server-exemplaar (), de database (Data SourceInitial Catalog), het schema (bijvoorbeelddbo) en de tabelnaam op (bijvoorbeeldTestCache):

dotnet sql-cache create "Data Source=(localdb)/MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache

Wanneer het hulpprogramma slaagt, wordt een bericht geregistreerd:

Table and index were created successfully.

De tabel die door het sql-cache hulpprogramma is gemaakt, heeft het volgende schema:

Schermafbeelding met het schema van een SQL Server cachetabel die is gemaakt met de opdracht sql-cache create.

Note

Een app moet cachewaarden manipuleren met behulp van een exemplaar van IDistributedCache, niet een exemplaar van SqlServerCache.

De voorbeeld-app implementeert de SqlServerCache klasse in een niet-ontwikkelingsomgeving (Development) in het bestand Program.cs :

builder.Services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = builder.Configuration.GetConnectionString(
        "DistCache_ConnectionString");
    options.SchemaName = "dbo";
    options.TableName = "TestCache";
});

Note

Eigenschappen zoals ConnectionString (en optioneel SchemaName en) TableNameworden doorgaans buiten broncodebeheer opgeslagen. Bijvoorbeeld de Secret Manager of de appsettings.json of appsettings.{Omgeving}.json bestanden kunnen de eigenschappen opslaan. De verbindingsreeks kan referenties bevatten die buiten broncodebeheersystemen moeten worden bewaard.

Zie SQL-database op Azure voor meer informatie.

Gedistribueerde Postgres-cache

Azure Database for PostgreSQL kan worden gebruikt als een gedistribueerde opslag voor cachebacking via de IDistributedCache interface. Azure Database for PostgreSQL is een volledig beheerde, ai-ready DBaaS-aanbieding (Database-as-a-Service) die is gebouwd op de opensource PostgreSQL-engine. Het ontwerp ondersteunt bedrijfskritieke workloads met voorspelbare prestaties, robuuste beveiliging, hoge beschikbaarheid en naadloze schaalbaarheid.

Nadat u het NuGet-pakket Microsoft.Extensions.Caching.Postgres hebt geïnstalleerd, configureert u de gedistribueerde cache als volgt:

  1. Registreer de dienst.

    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();
    
  2. Gebruik de 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;
        }
    }
    

Gedistribueerde NCache-geheugenopslag

NCache is een open source in-memory gedistribueerde cache die in .NET native is ontwikkeld. NCache werkt zowel lokaal als geconfigureerd als een gedistribueerd cachecluster voor een ASP.NET Core-app die wordt uitgevoerd in Azure of op andere hostingplatforms.

Als u NCache op uw lokale computer wilt installeren en configureren, raadpleegt u de Handleiding Aan de slag.

NCache configureren:

  1. Installeer het NuGet-pakket NCache SDK, dat NCache Opensource ondersteunt voor .NET Framework- en .NET Core-apps.

  2. Configureer het cachecluster in de clientconfiguratie (het bestand client.ncconf ).

  3. Voeg de volgende code toe aan het bestand Program.cs :

builder.Services.AddNCacheDistributedCache(configuration =>
{
    configuration.CacheName = "democache";
    configuration.EnableLogs = true;
    configuration.ExceptionsEnabled = true;
});

Gedistribueerde Azure Cosmos DB-cache

Azure Cosmos DB kan worden geconfigureerd in ASP.NET Core als een sessiestatusprovider met behulp van de interface IDistributedCache. Azure Cosmos DB is een volledig beheerde NoSQL- en relationele database voor moderne app-ontwikkeling die hoge beschikbaarheid, schaalbaarheid en toegang met lage latentie tot gegevens biedt voor bedrijfskritieke toepassingen.

Nadat u de Microsoft. Extensions.Caching.Cosmos NuGet-pakket, configureert u een Azure Cosmos DB gedistribueerde cache. U kunt een bestaande Azure Cosmos DB-client gebruiken of een nieuwe maken, zoals beschreven in de volgende secties.

Zie de Microsoft Cache-extensie met Azure Cosmos DB, het README-bestand van de GitHub-opslagplaats voor het NuGet-pakket voor meer informatie.

Een bestaande client opnieuw gebruiken

De eenvoudigste manier om een gedistribueerde cache te configureren, is door een bestaande Azure Cosmos DB-client opnieuw te gebruiken. In dit geval wordt het CosmosClient exemplaar niet verwijderd wanneer de provider wordt verwijderd.

services.AddCosmosCache((CosmosCacheOptions cacheOptions) =>
{
    cacheOptions.ContainerName = Configuration["CosmosCacheContainer"];
    cacheOptions.DatabaseName = Configuration["CosmosCacheDatabase"];
    cacheOptions.CosmosClient = existingCosmosClient;
    cacheOptions.CreateIfNotExists = true;
});

Een nieuwe client maken

U kunt ook een nieuwe client instantiëren. In dit geval wordt de CosmosClient instance vrijgegeven wanneer de provider wordt vrijgegeven.

services.AddCosmosCache((CosmosCacheOptions cacheOptions) =>
{
    cacheOptions.ContainerName = Configuration["CosmosCacheContainer"];
    cacheOptions.DatabaseName = Configuration["CosmosCacheDatabase"];
    cacheOptions.ClientBuilder = new CosmosClientBuilder(Configuration["CosmosConnectionString"]);
    cacheOptions.CreateIfNotExists = true;
});

De gedistribueerde cache gebruiken

Als u de IDistributedCache interface wilt gebruiken, vraagt u in de app een exemplaar van IDistributedCache aan. Het exemplaar wordt door middel van afhankelijkheidsinjectie (DI) geleverd.

Wanneer de voorbeeld-app wordt gestart, wordt het IDistributedCache exemplaar in het Program.cs-bestand geïnjecteerd. De huidige tijd wordt in de cache opgeslagen met behulp van de IHostApplicationLifetime interface. (Zie .NET Generic Host: IHostApplicationLifetime voor meer informatie.)

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);
});

De voorbeeldapp injecteert het IDistributedCache exemplaar in het IndexModel object voor gebruik door de Indexpagina.

Telkens wanneer de indexpagina wordt geladen, wordt de cache gecontroleerd op de tijd in de cache met behulp van de OnGetAsync methode. Als de tijd in de cache niet is verlopen, wordt de tijd weergegeven. Als 20 seconden zijn verstreken sinds de laatste keer dat de tijd in de cache is geopend (de laatste keer dat deze pagina is geladen), wordt op de pagina het bericht ' In cache verstreken tijd' weergegeven.

Werk de tijd in de cache onmiddellijk bij naar de huidige tijd door de optie Tijd in cache opnieuw instellen te selecteren. Met deze actie wordt de OnPostResetCachedTime handlermethode geactiveerd.

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

U hoeft geen Singleton- of Scoped-levensduur te gebruiken voor IDistributedCache exemplaren met een ingebouwde implementatie.

U kunt ook een IDistributedCache instantie maken waar u er mogelijk een nodig hebt in plaats van DI te gebruiken. Het maken van een exemplaar in code kan het echter moeilijker maken om uw code te testen en schendt het principe expliciete afhankelijkheden.

Aanbevelingen voor cache bekijken

Wanneer u besluit welke implementatie van de interface het IDistributedCache beste is voor uw app, moet u rekening houden met de volgende punten:

  • Bestaande infrastructuur
  • Prestatievereisten
  • Cost
  • Teamervaring

Cachingoplossingen zijn meestal afhankelijk van opslag in het geheugen om snel gegevens in de cache op te halen, maar geheugen is een beperkte resource en kostbaar om uit te breiden. Sla veelgebruikte gegevens alleen op in een cache.

Voor de meeste apps biedt een Redis-cache een hogere doorvoer en lagere latentie dan een SQL Server-cache. Benchmarking wordt echter aanbevolen om de prestatiekenmerken van cachestrategieën te bepalen.

Als SQL Server de gedeelde cache-backend is en het opslaan/oproepen van cache- en app-gegevens uit dezelfde database plaatsvinden, kan de prestatie verminderen. De aanbevolen methode is om een toegewezen SQL Server exemplaar te gebruiken voor de gedistribueerde cachebackingopslag.

Een gedistribueerde cache is een cache die wordt gedeeld door meerdere app-servers, die doorgaans worden onderhouden als een externe service voor de app-servers die er toegang toe hebben. Een gedistribueerde cache kan de prestaties en schaalbaarheid van een ASP.NET Core-app verbeteren, met name wanneer de app wordt gehost door een cloudservice of een serverfarm.

Een gedistribueerde cache heeft verschillende voordelen ten opzichte van andere cachescenario's waarbij gegevens in de cache worden opgeslagen op afzonderlijke app-servers.

Wanneer gegevens in de cache worden gedistribueerd, worden de gegevens als volgt verdeeld:

  • Is coherent (consistent) tussen aanvragen naar meerdere servers.
  • Overleeft het opnieuw opstarten van de server en app-implementaties.
  • Gebruikt geen lokaal geheugen.

Configuratie van gedistribueerde cache is implementatiespecifiek. In dit artikel wordt beschreven hoe u gedistribueerde SQL Server-, Redis- en Postgres-caches configureert. Implementaties van derden zijn ook beschikbaar, zoals NCache (NCache op GitHub). Ongeacht welke implementatie is geselecteerd, communiceert de app met de cache via de IDistributedCache interface.

Voorbeeldcode bekijken of downloaden (hoe download je)

Prerequisites

Voeg een pakketverwijzing toe voor de gedistribueerde cacheprovider die wordt gebruikt:

IDistributedCache interface

De IDistributedCache interface biedt de volgende methoden voor het bewerken van items in de implementatie van de gedistribueerde cache:

  • Get, : GetAsyncAccepteert een tekenreekssleutel en haalt een item in de cache op als een byte[] matrix als deze in de cache wordt gevonden.
  • Set, SetAsync: Voegt een item (als byte[] array) toe aan de cache met behulp van een tekenreekssleutel.
  • Refresh, RefreshAsync: Hiermee vernieuwt u een item in de cache op basis van de sleutel en stelt u de time-out voor verschuivende verlooptijd opnieuw in (indien van toepassing).
  • Remove, : RemoveAsyncVerwijdert een cache-item op basis van de tekenreekssleutel.

Gedistribueerde cachingservices instellen

Registreer een implementatie van IDistributedCache in Program.cs. Door framework geleverde implementaties die in dit onderwerp worden beschreven, zijn onder andere:

Gedistribueerde Redis-cache

We raden aan productie-apps de gedistribueerde Redis-cache te gebruiken, omdat deze het meest presterende is. Zie Aanbevelingen voor meer informatie.

Redis is een opensource-gegevensarchief in het geheugen, dat vaak wordt gebruikt als een gedistribueerde cache. U kunt een Azure Redis Cache configureren voor een door Azure gehoste ASP.NET Core-app en een Azure Redis Cache gebruiken voor lokale ontwikkeling.

Een app configureert de cache-implementatie met behulp van een RedisCache exemplaar (AddStackExchangeRedisCache).

  1. Maak een Azure Cache voor Redis.
  2. Kopieer de primaire verbindingsreeks (StackExchange.Redis) naar Configuratie.
    • Lokale ontwikkeling: Sla de connectiestring op met Secret Manager.
    • Azure: Sla de verbindingsreeks op in een beveiligd archief, zoals Azure Key Vault

Met de volgende code wordt Azure Cache voor Redis ingeschakeld:

builder.Services.AddStackExchangeRedisCache(options =>
 {
     options.Configuration = builder.Configuration.GetConnectionString("MyRedisConStr");
     options.InstanceName = "SampleInstance";
 });

In de voorgaande code wordt ervan uitgegaan dat de primaire verbindingsreeks (StackExchange.Redis) is opgeslagen in de configuratie met de sleutelnaam MyRedisConStr.

Zie Azure Cache voor Redis voor meer informatie.

Bekijk dit GitHub-probleem voor een discussie over alternatieve benaderingen voor een lokale Redis-cache.

Gedistribueerde geheugencache

De gedistribueerde geheugencache (AddDistributedMemoryCache) is een framework-implementatie van IDistributedCache die items in het geheugen opslaat. De gedistribueerde geheugencache is geen werkelijke gedistribueerde cache. Items in de cache worden opgeslagen door het app-exemplaar op de server waarop de app wordt uitgevoerd.

De gedistribueerde geheugencache is een nuttige implementatie:

  • In ontwikkelings- en testscenario's.
  • Wanneer één server wordt gebruikt in productie en geheugenverbruik geen probleem is. Door de gedistribueerde geheugencache te implementeren, wordt gegevensopslag in de cache geabstraheerd. Hiermee kunt u in de toekomst een echte oplossing voor gedistribueerde caching implementeren als meerdere knooppunten of fouttolerantie nodig zijn.

De voorbeeld-app maakt gebruik van de gedistribueerde geheugencache wanneer de app wordt uitgevoerd in de Development omgeving in Program.cs:

builder.Services.AddDistributedMemoryCache();

Gedistribueerde SQL Server-cache

Met de implementatie van gedistribueerde SQL Server-cache (AddDistributedSqlServerCache) kan de gedistribueerde cache een SQL Server-database gebruiken als back-uparchief. Als u een sql Server-itemtabel in de cache wilt maken in een SQL Server-exemplaar, kunt u het sql-cache hulpprogramma gebruiken. Met het hulpprogramma maakt u een tabel met de naam en het schema dat u opgeeft.

Maak een tabel in SQL Server door de opdracht uit te sql-cache create voeren. Geef het SQL Server-exemplaar (), de database (Data SourceInitial Catalog), het schema (bijvoorbeelddbo) en de tabelnaam op (bijvoorbeeldTestCache):

dotnet sql-cache create "Data Source=(localdb)/MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache

Er wordt een bericht geregistreerd om aan te geven dat het hulpprogramma is geslaagd:

Table and index were created successfully.

De tabel die door het sql-cache hulpprogramma is gemaakt, heeft het volgende schema:

SqlServer Cache-tabel

Note

Een app moet cachewaarden manipuleren met behulp van een exemplaar van IDistributedCache, niet een SqlServerCache.

De voorbeeld-app implementeert SqlServerCache in een niet-Development-omgeving in Program.cs:

builder.Services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = builder.Configuration.GetConnectionString(
        "DistCache_ConnectionString");
    options.SchemaName = "dbo";
    options.TableName = "TestCache";
});

Note

A ConnectionString (en optioneel SchemaName en TableName) wordt meestal buiten broncodebeheer opgeslagen (bijvoorbeeld opgeslagen door Secret Manager of in appsettings.json/appsettings.{Environment}.json bestanden). De verbindingsreeks kan referentiegegevens bevatten die buiten bereik moeten blijven van broncodebeheersystemen.

Gedistribueerde Postgres-cache

Azure Database for PostgreSQL kan worden gebruikt als een gedistribueerde opslag voor cachebacking via de IDistributedCache interface. Azure Database for PostgreSQL is een volledig beheerde, ai-ready Database-as-a-Service (DBaaS) die is gebouwd op de opensource PostgreSQL-engine, ontworpen ter ondersteuning van bedrijfskritieke workloads met voorspelbare prestaties, robuuste beveiliging, hoge beschikbaarheid en naadloze schaalbaarheid.

Nadat u het NuGet-pakket Microsoft.Extensions.Caching.Postgres hebt geïnstalleerd, configureert u de gedistribueerde cache als volgt:

  1. De service registreren
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();
  1. De cache gebruiken
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;
    }
}

Gedistribueerde NCache-cache

NCache is een open source gedistribueerde cache die systeemeigen is ontwikkeld in .NET en .NET Core. NCache werkt zowel lokaal als geconfigureerd als een gedistribueerd cachecluster voor een ASP.NET Core-app die wordt uitgevoerd in Azure of op andere hostingplatforms.

Zie Introductiehandleiding voor Windows (.NET en .NET Core) als u NCache op uw lokale computer wilt installeren en configureren.

NCache configureren:

  1. Installeer NCache open source NuGet.
  2. Configureer het cachecluster in client.ncconf.
  3. Voeg de volgende code toe aan Program.cs:
builder.Services.AddNCacheDistributedCache(configuration =>
{
    configuration.CacheName = "democache";
    configuration.EnableLogs = true;
    configuration.ExceptionsEnabled = true;
});

De gedistribueerde cache gebruiken

Als u de IDistributedCache interface wilt gebruiken, vraagt u in de app een exemplaar van IDistributedCache aan. Het exemplaar wordt door middel van afhankelijkheidsinjectie (DI) geleverd.

Wanneer de voorbeeld-app wordt gestart, wordt IDistributedCache in Program.cs geïnjecteerd. De huidige tijd wordt in de cache opgeslagen met behulp van IHostApplicationLifetime (zie Generic Host: IHostApplicationLifetime) voor meer informatie:

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);
});

De voorbeeld-app injecteert IDistributedCache in de IndexModel voor gebruik door de Index-pagina.

Telkens wanneer de Indexpagina wordt geladen, wordt de cache gecontroleerd op de gecachete tijd in OnGetAsync. Als de tijd in de cache niet is verlopen, wordt de tijd weergegeven. Als 20 seconden zijn verstreken sinds de laatste keer dat de tijd in de cache is geopend (de laatste keer dat deze pagina is geladen), wordt op de pagina de verlopen tijd in de cache weergegeven.

Werk de gecachede tijd onmiddellijk bij naar de huidige tijd door de knop Gecachede Tijd Resetten te selecteren. Met de knop wordt de OnPostResetCachedTime handlermethode geactiveerd.

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();
    }
}

U hoeft geen Singleton- of Scoped-levensduur te gebruiken voor IDistributedCache exemplaren met de ingebouwde implementaties.

U kunt ook een IDistributedCache exemplaar maken waar u er mogelijk een nodig hebt in plaats van di te gebruiken, maar door een exemplaar in code te maken, kan uw code moeilijker worden getest en in strijd zijn met het principe expliciete afhankelijkheden.

Recommendations

Wanneer u besluit welke implementatie IDistributedCache het beste is voor uw app, moet u rekening houden met het volgende:

  • Bestaande infrastructuur
  • Prestatievereisten
  • Cost
  • Teamervaring

Cachingoplossingen zijn meestal afhankelijk van opslag in het geheugen om snel gegevens in de cache op te halen, maar geheugen is een beperkte resource en kostbaar om uit te breiden. Sla veelgebruikte gegevens alleen op in een cache.

Voor de meeste apps biedt een Redis-cache een hogere doorvoer en lagere latentie dan een SQL Server-cache. Benchmarking wordt echter aanbevolen om de prestatiekenmerken van cachestrategieën te bepalen.

Wanneer SQL Server wordt gebruikt als een gedistribueerde cache-backendopslag, kan het gebruik van dezelfde database voor zowel de cache als de gewone gegevensopslag en -opvraging van de app de prestaties van beide negatief beïnvloeden. U wordt aangeraden een dedicated SQL Server-instance te gebruiken voor de gedistribueerde cache opslag.

Aanvullende bronnen

Een gedistribueerde cache is een cache die wordt gedeeld door meerdere app-servers, die doorgaans worden onderhouden als een externe service voor de app-servers die er toegang toe hebben. Een gedistribueerde cache kan de prestaties en schaalbaarheid van een ASP.NET Core-app verbeteren, met name wanneer de app wordt gehost door een cloudservice of een serverfarm.

Een gedistribueerde cache heeft verschillende voordelen ten opzichte van andere cachescenario's waarbij gegevens in de cache worden opgeslagen op afzonderlijke app-servers.

Wanneer gegevens in de cache worden gedistribueerd, worden de gegevens als volgt verdeeld:

  • Is coherent (consistent) tussen aanvragen naar meerdere servers.
  • Overleeft het opnieuw opstarten van de server en app-implementaties.
  • Gebruikt geen lokaal geheugen.

Configuratie van gedistribueerde cache is implementatiespecifiek. In dit artikel wordt beschreven hoe u gedistribueerde SQL Server-, Redis- en Postgres-caches configureert. Implementaties van derden zijn ook beschikbaar, zoals NCache (NCache op GitHub). Ongeacht welke implementatie is geselecteerd, communiceert de app met de cache via de IDistributedCache interface.

Voorbeeldcode bekijken of downloaden (hoe download je)

Prerequisites

Als u een gedistribueerde SQL Server-cache wilt gebruiken, voegt u een pakketverwijzing toe aan het pakket Microsoft.Extensions.Caching.SqlServer .

Als u een gedistribueerde Redis-cache wilt gebruiken, voegt u een pakketverwijzing toe aan het pakket Microsoft.Extensions.Caching.StackExchangeRedis .

Als u een gedistribueerde Postgres-cache wilt gebruiken, voegt u een pakketverwijzing toe aan het pakket Microsoft.Extensions.Caching.Postgres .

Als u NCache gedistribueerde cache wilt gebruiken, voegt u een pakketverwijzing toe aan het pakket NCache.Microsoft.Extensions.Caching.OpenSource .

IDistributedCache-interface

De IDistributedCache interface biedt de volgende methoden voor het bewerken van items in de implementatie van de gedistribueerde cache:

  • Get, : GetAsyncAccepteert een tekenreekssleutel en haalt een item in de cache op als een byte[] matrix als deze in de cache wordt gevonden.
  • Set, SetAsync: Voegt een item (als byte[] array) toe aan de cache met behulp van een tekenreekssleutel.
  • Refresh, RefreshAsync: Hiermee vernieuwt u een item in de cache op basis van de sleutel en stelt u de time-out voor verschuivende verlooptijd opnieuw in (indien van toepassing).
  • Remove, : RemoveAsyncVerwijdert een cache-item op basis van de tekenreekssleutel.

Gedistribueerde cachingservices instellen

Registreer een implementatie van IDistributedCache in Startup.ConfigureServices. Door framework geleverde implementaties die in dit onderwerp worden beschreven, zijn onder andere:

Gedistribueerde geheugencache

De gedistribueerde geheugencache (AddDistributedMemoryCache) is een framework-implementatie van IDistributedCache die items in het geheugen opslaat. De gedistribueerde geheugencache is geen werkelijke gedistribueerde cache. Items in de cache worden opgeslagen door het app-exemplaar op de server waarop de app wordt uitgevoerd.

De gedistribueerde geheugencache is een nuttige implementatie:

  • In ontwikkelings- en testscenario's.
  • Wanneer één server wordt gebruikt in productie en geheugenverbruik geen probleem is. Door de gedistribueerde geheugencache te implementeren, wordt gegevensopslag in de cache geabstraheerd. Hiermee kunt u in de toekomst een echte oplossing voor gedistribueerde caching implementeren als meerdere knooppunten of fouttolerantie nodig zijn.

De voorbeeld-app maakt gebruik van de gedistribueerde geheugencache wanneer de app wordt uitgevoerd in de Development omgeving in Startup.ConfigureServices:

services.AddDistributedMemoryCache();

Gedistribueerde SQL Server-cache

Met de implementatie van gedistribueerde SQL Server-cache (AddDistributedSqlServerCache) kan de gedistribueerde cache een SQL Server-database gebruiken als back-uparchief. Als u een sql Server-itemtabel in de cache wilt maken in een SQL Server-exemplaar, kunt u het sql-cache hulpprogramma gebruiken. Met het hulpprogramma maakt u een tabel met de naam en het schema dat u opgeeft.

Maak een tabel in SQL Server door de opdracht uit te sql-cache create voeren. Geef het SQL Server-exemplaar (), de database (Data SourceInitial Catalog), het schema (bijvoorbeelddbo) en de tabelnaam op (bijvoorbeeldTestCache):

dotnet sql-cache create "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache

Er wordt een bericht geregistreerd om aan te geven dat het hulpprogramma is geslaagd:

Table and index were created successfully.

De tabel die door het sql-cache hulpprogramma is gemaakt, heeft het volgende schema:

SqlServer Cache-tabel

Note

Een app moet cachewaarden manipuleren met behulp van een exemplaar van IDistributedCache, niet een SqlServerCache.

De voorbeeld-app implementeert SqlServerCache in een niet-Development-omgeving in Startup.ConfigureServices:

services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = 
        _config["DistCache_ConnectionString"];
    options.SchemaName = "dbo";
    options.TableName = "TestCache";
});

Note

A ConnectionString (en optioneel SchemaName en TableName) wordt meestal buiten broncodebeheer opgeslagen (bijvoorbeeld opgeslagen door Secret Manager of in appsettings.json/appsettings.{Environment}.json bestanden). De verbindingsreeks kan referentiegegevens bevatten die buiten bereik moeten blijven van broncodebeheersystemen.

Gedistribueerde Redis-cache

Redis is een opensource-gegevensarchief in het geheugen, dat vaak wordt gebruikt als een gedistribueerde cache. U kunt een Azure Redis Cache configureren voor een door Azure gehoste ASP.NET Core-app en een Azure Redis Cache gebruiken voor lokale ontwikkeling.

Een app configureert de cache-implementatie met behulp van een RedisCache exemplaar (AddStackExchangeRedisCache).

  1. Maak een Azure Cache voor Redis.
  2. Kopieer de primaire verbindingsreeks (StackExchange.Redis) naar Configuratie.
    • Lokale ontwikkeling: Sla de connectiestring op met Secret Manager.
    • Azure: Sla de verbindingsreeks op in een beveiligd archief, zoals Azure Key Vault

Met de volgende code wordt Azure Cache voor Redis ingeschakeld:

public void ConfigureServices(IServiceCollection services)
{
    if (_hostContext.IsDevelopment())
    {
        services.AddDistributedMemoryCache();
    }
    else
    {
        services.AddStackExchangeRedisCache(options =>
        {
            options.Configuration = _config["MyRedisConStr"];
            options.InstanceName = "SampleInstance";
        });
    }

    services.AddRazorPages();
}

In de voorgaande code wordt ervan uitgegaan dat de primaire verbindingsreeks (StackExchange.Redis) is opgeslagen in de configuratie met de sleutelnaam MyRedisConStr.

Zie Azure Cache voor Redis voor meer informatie.

Bekijk dit GitHub-probleem voor een discussie over alternatieve benaderingen voor een lokale Redis-cache.

Gedistribueerde Postgres-cache

Azure Database for PostgreSQL kan worden gebruikt als een gedistribueerde opslag voor cachebacking via de IDistributedCache interface. Azure Database for PostgreSQL is een volledig beheerde, ai-ready Database-as-a-Service (DBaaS) die is gebouwd op de opensource PostgreSQL-engine, ontworpen ter ondersteuning van bedrijfskritieke workloads met voorspelbare prestaties, robuuste beveiliging, hoge beschikbaarheid en naadloze schaalbaarheid.

Nadat u het NuGet-pakket Microsoft.Extensions.Caching.Postgres hebt geïnstalleerd, configureert u de gedistribueerde cache als volgt:

  1. De service registreren
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();
  1. De cache gebruiken
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;
    }
}

Gedistribueerde NCache-cache

NCache is een open source gedistribueerde cache die systeemeigen is ontwikkeld in .NET en .NET Core. NCache werkt zowel lokaal als geconfigureerd als een gedistribueerd cachecluster voor een ASP.NET Core-app die wordt uitgevoerd in Azure of op andere hostingplatforms.

Zie Introductiehandleiding voor Windows (.NET en .NET Core) als u NCache op uw lokale computer wilt installeren en configureren.

NCache configureren:

  1. Installeer NCache open source NuGet.

  2. Configureer het cachecluster in client.ncconf.

  3. Voeg de volgende code toe aan Startup.ConfigureServices:

    services.AddNCacheDistributedCache(configuration =>    
    {        
        configuration.CacheName = "demoClusteredCache";
        configuration.EnableLogs = true;
        configuration.ExceptionsEnabled = true;
    });
    

De gedistribueerde cache gebruiken

Als u de IDistributedCache-interface wilt gebruiken, vraagt u een exemplaar van IDistributedCache aan vanuit elke constructor in de app. Het exemplaar wordt door middel van afhankelijkheidsinjectie (DI) geleverd.

Wanneer de voorbeeld-app wordt gestart, wordt IDistributedCache in Startup.Configure geïnjecteerd. De huidige tijd wordt in de cache opgeslagen met behulp van IHostApplicationLifetime (zie Generic Host: IHostApplicationLifetime) voor meer informatie:

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);
    });

De voorbeeld-app injecteert IDistributedCache in de IndexModel voor gebruik door de Index-pagina.

Telkens wanneer de Indexpagina wordt geladen, wordt de cache gecontroleerd op de gecachete tijd in OnGetAsync. Als de tijd in de cache niet is verlopen, wordt de tijd weergegeven. Als 20 seconden zijn verstreken sinds de laatste keer dat de tijd in de cache is geopend (de laatste keer dat deze pagina is geladen), wordt op de pagina de verlopen tijd in de cache weergegeven.

Werk de gecachede tijd onmiddellijk bij naar de huidige tijd door de knop Gecachede Tijd Resetten te selecteren. Met de knop wordt de OnPostResetCachedTime handlermethode geactiveerd.

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

U hoeft geen Singleton- of Scoped-levensduur te gebruiken voor IDistributedCache exemplaren (ten minste voor de ingebouwde implementaties).

U kunt ook een IDistributedCache exemplaar maken waar u er mogelijk een nodig hebt in plaats van di te gebruiken, maar door een exemplaar in code te maken, kan uw code moeilijker worden getest en in strijd zijn met het principe expliciete afhankelijkheden.

Recommendations

Wanneer u besluit welke implementatie IDistributedCache het beste is voor uw app, moet u rekening houden met het volgende:

  • Bestaande infrastructuur
  • Prestatievereisten
  • Cost
  • Teamervaring

Cachingoplossingen zijn meestal afhankelijk van opslag in het geheugen om snel gegevens in de cache op te halen, maar geheugen is een beperkte resource en kostbaar om uit te breiden. Sla veelgebruikte gegevens alleen op in een cache.

Over het algemeen biedt een Redis-cache een hogere doorvoer en lagere latentie dan een SQL Server-cache. Benchmarking is echter meestal vereist om de prestatiekenmerken van cachestrategieën te bepalen.

Wanneer SQL Server wordt gebruikt als een gedistribueerde cache-backendopslag, kan het gebruik van dezelfde database voor zowel de cache als de gewone gegevensopslag en -opvraging van de app de prestaties van beide negatief beïnvloeden. U wordt aangeraden een dedicated SQL Server-instance te gebruiken voor de gedistribueerde cache opslag.

Aanvullende bronnen