Verteiltes Zwischenspeichern in ASP.NET Core

Von Mohsin Nasir und smandia

Hinweis

Dies ist nicht die neueste Version dieses Artikels. Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

Wichtig

Diese Informationen beziehen sich auf ein Vorabversionsprodukt, das vor der kommerziellen Freigabe möglicherweise noch wesentlichen Änderungen unterliegt. Microsoft gibt keine Garantie, weder ausdrücklich noch impliziert, hinsichtlich der hier bereitgestellten Informationen.

Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

Ein verteilter Cache ist ein Cache, der von mehreren App-Servern gemeinsam genutzt wird und in der Regel als externer Dienst für die App-Server verwaltet wird, die darauf zugreifen. Ein verteilter Cache kann die Leistung und Skalierbarkeit einer ASP.NET Core-App verbessern, insbesondere wenn die App von einem Clouddienst oder einer Serverfarm gehostet wird.

Ein verteilter Cache hat mehrere Vorteile gegenüber anderen Zwischenspeicherungsszenarien, in denen zwischengespeicherte Daten auf einzelnen App-Servern gespeichert werden.

Wenn zwischengespeicherte Daten verteilt werden, gilt für sie Folgendes:

  • Sie sind kohärent (konsistent) für Anforderungen an mehrere Server.
  • Sie überleben Serverneustarts und App-Bereitstellungen.
  • Sie verwenden keinen lokalen Arbeitsspeicher.

Die Konfiguration des verteilten Cache ist implementierungsspezifisch. In diesem Artikel wird beschrieben, wie Sie verteilte Caches von SQL Server und Redis konfigurieren. Drittanbieterimplementierungen sind ebenfalls verfügbar, z. B. NCache (NCache auf GitHub). Unabhängig davon, welche Implementierung ausgewählt ist, interagiert die App über die Schnittstelle IDistributedCache mit dem Cache.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

Voraussetzungen

Fügen Sie einen Paketverweis für den verwendeten verteilten Cacheanbieter hinzu:

IDistributedCache-Schnittstelle

Die IDistributedCache-Schnittstelle bietet die folgenden Methoden zum Bearbeiten von Elementen bei der Implementierung des verteilten Cache:

  • Get, GetAsync: Akzeptiert einen Zeichenfolgenschlüssel und ruft ein zwischengespeichertes Element als byte[]-Array ab, wenn es im Cache gefunden wird.
  • Set, SetAsync: Fügt dem Cache mithilfe eines Zeichenfolgenschlüssels ein Element (als byte[]-Array) hinzu.
  • Refresh, RefreshAsync: Aktualisiert ein Element im Cache auf Grundlage seines Schlüssels und setzt das gleitende Ablauftimeout (sofern vorhanden) zurück.
  • Remove, RemoveAsync: Entfernt ein Cacheelement anhand seines Zeichenfolgenschlüssels.

Einrichten verteilter Zwischenspeicherdienste

Registrieren Sie eine Implementierung von IDistributedCache in Program.cs. Im Framework bereitgestellte Implementierungen, die in diesem Thema beschrieben werden, umfassen:

Verteilter Redis-Cache

Es wird empfohlen, dass Produktions-Apps den verteilten Redis-Cache verwenden, da er am leistungsfähigsten ist. Weitere Informationen finden Sie unter Empfehlungen.

Redis ist ein Open Source In-Memory-Datenspeicher, der häufig als verteilter Cache verwendet wird. Sie können eine Azure Cache for Redis-Instanz für eine von Azure gehostete ASP.NET Core-App konfigurieren und eine Azure Cache for Redis-Instanz für die lokale Entwicklung verwenden.

Eine App konfiguriert die Cacheimplementierung mithilfe einer RedisCache-Instanz durch Aufrufen von AddStackExchangeRedisCache. Für die Ausgabezwischenspeicherung verwenden Sie AddStackExchangeRedisOutputCache.

  1. Erstellen Sie einen Azure Cache for Redis.
  2. Kopieren Sie die primäre Verbindungszeichenfolge (StackExchange.Redis) in Configuration.
    • Lokale Entwicklung: Speichern Sie die Verbindungszeichenfolge mit Secret Manager.
    • Azure: Speichern Sie die Verbindungszeichenfolge in der App Service Configuration oder in einem anderen sicheren Speicher.

Der folgende Code aktiviert Azure Cache for Redis:

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

Im vorherigen Code wird davon ausgegangen, dass die primäre Verbindungszeichenfolge (StackExchange.Redis) in Configuration mit dem Schlüsselnamen MyRedisConStrgespeichert wurde.

Weitere Informationen finden Sie unter Azure Cache for Redis.

In diesem GitHub-Problem finden Sie eine Diskussion zu alternativen Ansätzen für einen lokalen Redis-Cache.

Verteilter Speichercache

Der verteilte Speichercache (AddDistributedMemoryCache) ist eine vom Framework bereitgestellte Implementierung von IDistributedCache, die Elemente im Arbeitsspeicher speichert. Der verteilte Speichercache ist kein tatsächlich verteilter Cache. Zwischengespeicherte Elemente werden von der App-Instanz auf dem Server gespeichert, auf dem die App ausgeführt wird.

Der verteilte Speichercache ist eine nützliche Implementierung:

  • In Entwicklungs- und Testszenarien.
  • Wenn ein einzelner Server in der Produktion verwendet wird und die Arbeitsspeichernutzung kein Problem ist. Durch die Implementierung des verteilten Speichercache wird die Speicherung von Cachedaten abstrahiert. Dies ermöglicht die Implementierung einer echten verteilten Zwischenspeicherungslösung in der Zukunft, wenn mehrere Knoten oder Fehlertoleranz erforderlich werden.

Die Beispiel-App verwendet den verteilten Speichercache, wenn die App in der Entwicklungsumgebung in Program.csausgeführt wird:

builder.Services.AddDistributedMemoryCache();

Verteilter SQL Server-Cache

Die Implementierung des verteilten SQL Server-Cache (AddDistributedSqlServerCache) ermöglicht es dem verteilten Cache, eine SQL Server-Datenbank als Sicherungsspeicher zu verwenden. Um eine zwischengespeicherte SQL Server.Elementtabelle in einer SQL Server-Instanz zu erstellen, können Sie das Tool sql-cache verwenden. Das Tool erstellt eine Tabelle mit dem von Ihnen angegebenen Namen und Schema.

Erstellen Sie eine Tabelle in SQL Server, indem Sie den Befehl sql-cache create ausführen. Geben Sie die SQL Server-Instanz (Data Source), die Datenbank (Initial Catalog), das Schema (z. B. dbo) und den Tabellennamen (z. B. TestCache) an:

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

Eine Meldung wird protokolliert, um anzugeben, dass das Tool erfolgreich war:

Table and index were created successfully.

Die vom sql-cache-Tool erstellte Tabelle weist das folgende Schema auf:

SqlServer-Cache-Tabelle

Hinweis

Eine App sollte Cachewerte mithilfe einer Instanz von IDistributedCache, nicht von SqlServerCache, bearbeiten.

Die Beispiel-App implementiert SqlServerCache in einer Nicht-Entwicklungsumgebung in Program.cs:

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

Hinweis

ConnectionString sowie optional SchemaName und TableName werden in der Regel außerhalb der Quellcodeverwaltung gespeichert (z. B. vom Secret Manager oder in appsettings.json/appsettings.{Environment}.json-Dateien gespeichert). Die Verbindungszeichenfolge kann Anmeldeinformationen enthalten, die außerhalb der Quellcodeverwaltungssysteme aufbewahrt werden sollten.

Verteilter NCache-Cache

NCache ist ein verteilter Open Source In-Memory-Cache, der nativ in .NET und .NET Core entwickelt wurde. NCache funktioniert sowohl lokal als auch als verteilter Cachecluster für eine ASP.NET Core-App, die in Azure oder auf anderen Hostingplattformen ausgeführt wird.

Informationen zum Installieren und Konfigurieren von NCache auf Ihrem lokalen Computer finden Sie unter Leitfaden mit ersten Schritten für Windows (.NET und .NET Core).

So konfigurieren Sie NCache:

  1. Installieren Sie NCache Open Source NuGet.
  2. Konfigurieren Sie den Cachecluster in client.ncconf.
  3. Fügen Sie den folgenden Code zu Program.cs hinzu:
builder.Services.AddNCacheDistributedCache(configuration =>
{
    configuration.CacheName = "democache";
    configuration.EnableLogs = true;
    configuration.ExceptionsEnabled = true;
});

Verteilter Azure CosmosDB Cache

Azure Cosmos DB kann in ASP.NET Core als Sitzungszustandsanbieter mithilfe der IDistributedCache-Schnittstelle verwendet werden. Azure Cosmos DB ist eine vollständig verwaltete NoSQL- und relationale Datenbank für die moderne Anwendungsentwicklung, die hohe Verfügbarkeit, Skalierbarkeit und Zugriff auf Daten mit geringer Latenz für unternehmenskritische Anwendungen bietet.

Konfigurieren Sie nach der Installation des Microsoft.Extensions.Caching.Cosmos NuGet-Pakets einen verteilten Azure Cosmos DB-Cache wie folgt:

Wiederverwenden eines vorhandenen Clients

Die einfachste Möglichkeit zum Konfigurieren des verteilten Caches besteht darin, einen vorhandenen Azure Cosmos DB-Client erneut zu verwenden. In diesem Fall wird die CosmosClient-Instanz nicht verworfen, wenn der Anbieter verworfen wird.

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

Erstellen eines neuen Clients

Alternativ können Sie einen neuen Client instanziieren. In diesem Fall wird die CosmosClient-Instanz gelöscht, wenn der Anbieter verworfen wird.

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

Verwenden des verteilten Cache

Um die IDistributedCache-Schnittstelle zu verwenden, fordern Sie eine Instanz von IDistributedCache in der App an. Die Instanz wird durch Abhängigkeitsinjektion (Dependency Injection, DI) bereitgestellt.

Wenn die Beispiel-App gestartet wird, wird IDistributedCache in Program.cseingebracht. Die aktuelle Zeit wird mit IHostApplicationLifetime zwischengespeichert (weitere Informationen finden Sie unter Generischer Host: 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);
});

Die Beispiel-App bringt IDistributedCache zwecks Verwendung durch die Indexseite in IndexModel ein.

Jedes Mal, wenn die Indexseite geladen wird, wird der Cache auf die zwischengespeicherte Zeit in OnGetAsyncüberprüft. Wenn die zwischengespeicherte Zeit nicht abgelaufen ist, wird die Uhrzeit angezeigt. Wenn seit dem letzten Zugriff auf die zwischengespeicherte Zeit (das letzte Laden dieser Seite) 20 Sekunden verstrichen sind, wird auf der Seite Zwischengespeicherte Zeit abgelaufen angezeigt.

Aktualisieren Sie sofort die zwischengespeicherte Zeit auf die aktuelle Zeit, indem Sie die Schaltfläche Zwischengespeicherte Zeit zurücksetzen auswählen. Die Schaltfläche löst die Handlermethode OnPostResetCachedTime aus.

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

Es ist nicht erforderlich, eine Singleton- oder bereichsbezogene Lebensdauer für IDistributedCache-Instanzen mit den integrierten Implementierungen zu verwenden.

Sie können zudem eine IDistributedCache-Instanz überall dort erstellen, wo Sie anstelle von DI eine Instanz benötigen, aber das Erstellen einer Instanz im Code kann das Testen Ihres Codes erschweren und gegen das Prinzip der expliziten Abhängigkeiten verstoßen.

Empfehlungen

Bei der Entscheidung, welche Implementierung von IDistributedCache für Ihre App am besten geeignet ist, sollten Sie Folgendes berücksichtigen:

  • Vorhandene Infrastruktur
  • Leistungsanforderungen
  • Kosten
  • Teamerfahrung

Zwischenspeicherlösungen basieren in der Regel auf In-Memory-Speicher, um einen schnellen Abruf von zwischengespeicherten Daten zu ermöglichen. Der Arbeitsspeicher ist jedoch nur eine begrenzte Ressource und seine Erweiterung kostspielig. Speichern Sie nur häufig verwendete Daten in einem Cache.

Für die meisten Apps bietet ein Redis-Cache einen höheren Durchsatz und eine geringere Latenz als ein SQL Server-Cache. Es wird jedoch ein Benchmarking empfohlen, um die Leistungsmerkmale von Zwischenspeicherungsstrategien zu bestimmen.

Wenn SQL Server als verteilter Cachesicherungsspeicher verwendet wird, kann sich die Verwendung derselben Datenbank für den Cache und die normale Datenspeicherung der App und das Abrufen negativ auf die Leistung beider auswirken. Es wird empfohlen, eine dedizierte SQL Server-Instanz für den verteilten Cachesicherungsspeicher zu verwenden.

Zusätzliche Ressourcen

Ein verteilter Cache ist ein Cache, der von mehreren App-Servern gemeinsam genutzt wird und in der Regel als externer Dienst für die App-Server verwaltet wird, die darauf zugreifen. Ein verteilter Cache kann die Leistung und Skalierbarkeit einer ASP.NET Core-App verbessern, insbesondere wenn die App von einem Clouddienst oder einer Serverfarm gehostet wird.

Ein verteilter Cache hat mehrere Vorteile gegenüber anderen Zwischenspeicherungsszenarien, in denen zwischengespeicherte Daten auf einzelnen App-Servern gespeichert werden.

Wenn zwischengespeicherte Daten verteilt werden, gilt für sie Folgendes:

  • Sie sind kohärent (konsistent) für Anforderungen an mehrere Server.
  • Sie überleben Serverneustarts und App-Bereitstellungen.
  • Sie verwenden keinen lokalen Arbeitsspeicher.

Die Konfiguration des verteilten Cache ist implementierungsspezifisch. In diesem Artikel wird beschrieben, wie Sie verteilte Caches von SQL Server und Redis konfigurieren. Drittanbieterimplementierungen sind ebenfalls verfügbar, z. B. NCache (NCache auf GitHub). Unabhängig davon, welche Implementierung ausgewählt ist, interagiert die App über die Schnittstelle IDistributedCache mit dem Cache.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

Voraussetzungen

Fügen Sie einen Paketverweis für den verwendeten verteilten Cacheanbieter hinzu:

IDistributedCache-Schnittstelle

Die IDistributedCache-Schnittstelle bietet die folgenden Methoden zum Bearbeiten von Elementen bei der Implementierung des verteilten Cache:

  • Get, GetAsync: Akzeptiert einen Zeichenfolgenschlüssel und ruft ein zwischengespeichertes Element als byte[]-Array ab, wenn es im Cache gefunden wird.
  • Set, SetAsync: Fügt dem Cache mithilfe eines Zeichenfolgenschlüssels ein Element (als byte[]-Array) hinzu.
  • Refresh, RefreshAsync: Aktualisiert ein Element im Cache auf Grundlage seines Schlüssels und setzt das gleitende Ablauftimeout (sofern vorhanden) zurück.
  • Remove, RemoveAsync: Entfernt ein Cacheelement anhand seines Zeichenfolgenschlüssels.

Einrichten verteilter Zwischenspeicherdienste

Registrieren Sie eine Implementierung von IDistributedCache in Program.cs. Im Framework bereitgestellte Implementierungen, die in diesem Thema beschrieben werden, umfassen:

Verteilter Redis-Cache

Es wird empfohlen, dass Produktions-Apps den verteilten Redis-Cache verwenden, da er am leistungsfähigsten ist. Weitere Informationen finden Sie unter Empfehlungen.

Redis ist ein Open Source In-Memory-Datenspeicher, der häufig als verteilter Cache verwendet wird. Sie können einen Azure Redis Cache für eine von Azure gehostete ASP.NET Core-App konfigurieren und einen Azure Redis Cache für die lokale Entwicklung verwenden.

Eine App konfiguriert die Cacheimplementierung mithilfe einer RedisCache-Instanz (AddStackExchangeRedisCache).

  1. Erstellen Sie einen Azure Cache for Redis.
  2. Kopieren Sie die primäre Verbindungszeichenfolge (StackExchange.Redis) in Configuration.
    • Lokale Entwicklung: Speichern Sie die Verbindungszeichenfolge mit Secret Manager.
    • Azure: Speichern Sie die Verbindungszeichenfolge in der App Service Configuration oder in einem anderen sicheren Speicher.

Der folgende Code aktiviert Azure Cache for Redis:

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

Im vorherigen Code wird davon ausgegangen, dass die primäre Verbindungszeichenfolge (StackExchange.Redis) in Configuration mit dem Schlüsselnamen MyRedisConStrgespeichert wurde.

Weitere Informationen finden Sie unter Azure Cache for Redis.

In diesem GitHub-Problem finden Sie eine Diskussion zu alternativen Ansätzen für einen lokalen Redis-Cache.

Verteilter Speichercache

Der verteilte Speichercache (AddDistributedMemoryCache) ist eine vom Framework bereitgestellte Implementierung von IDistributedCache, die Elemente im Arbeitsspeicher speichert. Der verteilte Speichercache ist kein tatsächlich verteilter Cache. Zwischengespeicherte Elemente werden von der App-Instanz auf dem Server gespeichert, auf dem die App ausgeführt wird.

Der verteilte Speichercache ist eine nützliche Implementierung:

  • In Entwicklungs- und Testszenarien.
  • Wenn ein einzelner Server in der Produktion verwendet wird und die Arbeitsspeichernutzung kein Problem ist. Durch die Implementierung des verteilten Speichercache wird die Speicherung von Cachedaten abstrahiert. Dies ermöglicht die Implementierung einer echten verteilten Zwischenspeicherungslösung in der Zukunft, wenn mehrere Knoten oder Fehlertoleranz erforderlich werden.

Die Beispiel-App verwendet den verteilten Speichercache, wenn die App in der Entwicklungsumgebung in Program.csausgeführt wird:

builder.Services.AddDistributedMemoryCache();

Verteilter SQL Server-Cache

Die Implementierung des verteilten SQL Server-Cache (AddDistributedSqlServerCache) ermöglicht es dem verteilten Cache, eine SQL Server-Datenbank als Sicherungsspeicher zu verwenden. Um eine zwischengespeicherte SQL Server.Elementtabelle in einer SQL Server-Instanz zu erstellen, können Sie das Tool sql-cache verwenden. Das Tool erstellt eine Tabelle mit dem von Ihnen angegebenen Namen und Schema.

Erstellen Sie eine Tabelle in SQL Server, indem Sie den Befehl sql-cache create ausführen. Geben Sie die SQL Server-Instanz (Data Source), die Datenbank (Initial Catalog), das Schema (z. B. dbo) und den Tabellennamen (z. B. TestCache) an:

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

Eine Meldung wird protokolliert, um anzugeben, dass das Tool erfolgreich war:

Table and index were created successfully.

Die vom sql-cache-Tool erstellte Tabelle weist das folgende Schema auf:

SqlServer-Cache-Tabelle

Hinweis

Eine App sollte Cachewerte mithilfe einer Instanz von IDistributedCache, nicht von SqlServerCache, bearbeiten.

Die Beispiel-App implementiert SqlServerCache in einer Nicht-Entwicklungsumgebung in Program.cs:

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

Hinweis

ConnectionString sowie optional SchemaName und TableName werden in der Regel außerhalb der Quellcodeverwaltung gespeichert (z. B. vom Secret Manager oder in appsettings.json/appsettings.{Environment}.json-Dateien gespeichert). Die Verbindungszeichenfolge kann Anmeldeinformationen enthalten, die außerhalb der Quellcodeverwaltungssysteme aufbewahrt werden sollten.

Verteilter NCache-Cache

NCache ist ein verteilter Open Source In-Memory-Cache, der nativ in .NET und .NET Core entwickelt wurde. NCache funktioniert sowohl lokal als auch als verteilter Cachecluster für eine ASP.NET Core-App, die in Azure oder auf anderen Hostingplattformen ausgeführt wird.

Informationen zum Installieren und Konfigurieren von NCache auf Ihrem lokalen Computer finden Sie unter Leitfaden mit ersten Schritten für Windows (.NET und .NET Core).

So konfigurieren Sie NCache:

  1. Installieren Sie NCache Open Source NuGet.
  2. Konfigurieren Sie den Cachecluster in client.ncconf.
  3. Fügen Sie den folgenden Code zu Program.cs hinzu:
builder.Services.AddNCacheDistributedCache(configuration =>
{
    configuration.CacheName = "democache";
    configuration.EnableLogs = true;
    configuration.ExceptionsEnabled = true;
});

Verwenden des verteilten Cache

Um die IDistributedCache-Schnittstelle zu verwenden, fordern Sie eine Instanz von IDistributedCache in der App an. Die Instanz wird durch Abhängigkeitsinjektion (Dependency Injection, DI) bereitgestellt.

Wenn die Beispiel-App gestartet wird, wird IDistributedCache in Program.cseingebracht. Die aktuelle Zeit wird mit IHostApplicationLifetime zwischengespeichert (weitere Informationen finden Sie unter Generischer Host: 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);
});

Die Beispiel-App bringt IDistributedCache zwecks Verwendung durch die Indexseite in IndexModel ein.

Jedes Mal, wenn die Indexseite geladen wird, wird der Cache auf die zwischengespeicherte Zeit in OnGetAsyncüberprüft. Wenn die zwischengespeicherte Zeit nicht abgelaufen ist, wird die Uhrzeit angezeigt. Wenn seit dem letzten Zugriff auf die zwischengespeicherte Zeit (das letzte Laden dieser Seite) 20 Sekunden verstrichen sind, wird auf der Seite Zwischengespeicherte Zeit abgelaufen angezeigt.

Aktualisieren Sie sofort die zwischengespeicherte Zeit auf die aktuelle Zeit, indem Sie die Schaltfläche Zwischengespeicherte Zeit zurücksetzen auswählen. Die Schaltfläche löst die Handlermethode OnPostResetCachedTime aus.

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

Es ist nicht erforderlich, eine Singleton- oder bereichsbezogene Lebensdauer für IDistributedCache-Instanzen mit den integrierten Implementierungen zu verwenden.

Sie können zudem eine IDistributedCache-Instanz überall dort erstellen, wo Sie anstelle von DI eine Instanz benötigen, aber das Erstellen einer Instanz im Code kann das Testen Ihres Codes erschweren und gegen das Prinzip der expliziten Abhängigkeiten verstoßen.

Empfehlungen

Bei der Entscheidung, welche Implementierung von IDistributedCache für Ihre App am besten geeignet ist, sollten Sie Folgendes berücksichtigen:

  • Vorhandene Infrastruktur
  • Leistungsanforderungen
  • Kosten
  • Teamerfahrung

Zwischenspeicherlösungen basieren in der Regel auf In-Memory-Speicher, um einen schnellen Abruf von zwischengespeicherten Daten zu ermöglichen. Der Arbeitsspeicher ist jedoch nur eine begrenzte Ressource und seine Erweiterung kostspielig. Speichern Sie nur häufig verwendete Daten in einem Cache.

Für die meisten Apps bietet ein Redis-Cache einen höheren Durchsatz und eine geringere Latenz als ein SQL Server-Cache. Es wird jedoch ein Benchmarking empfohlen, um die Leistungsmerkmale von Zwischenspeicherungsstrategien zu bestimmen.

Wenn SQL Server als verteilter Cachesicherungsspeicher verwendet wird, kann sich die Verwendung derselben Datenbank für den Cache und die normale Datenspeicherung der App und das Abrufen negativ auf die Leistung beider auswirken. Es wird empfohlen, eine dedizierte SQL Server-Instanz für den verteilten Cachesicherungsspeicher zu verwenden.

Zusätzliche Ressourcen

Ein verteilter Cache ist ein Cache, der von mehreren App-Servern gemeinsam genutzt wird und in der Regel als externer Dienst für die App-Server verwaltet wird, die darauf zugreifen. Ein verteilter Cache kann die Leistung und Skalierbarkeit einer ASP.NET Core-App verbessern, insbesondere wenn die App von einem Clouddienst oder einer Serverfarm gehostet wird.

Ein verteilter Cache hat mehrere Vorteile gegenüber anderen Zwischenspeicherungsszenarien, in denen zwischengespeicherte Daten auf einzelnen App-Servern gespeichert werden.

Wenn zwischengespeicherte Daten verteilt werden, gilt für sie Folgendes:

  • Sie sind kohärent (konsistent) für Anforderungen an mehrere Server.
  • Sie überleben Serverneustarts und App-Bereitstellungen.
  • Sie verwenden keinen lokalen Arbeitsspeicher.

Die Konfiguration des verteilten Cache ist implementierungsspezifisch. In diesem Artikel wird beschrieben, wie Sie verteilte Caches von SQL Server und Redis konfigurieren. Drittanbieterimplementierungen sind ebenfalls verfügbar, z. B. NCache (NCache auf GitHub). Unabhängig davon, welche Implementierung ausgewählt ist, interagiert die App über die Schnittstelle IDistributedCache mit dem Cache.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

Voraussetzungen

Um einen verteilten SQL Server-Cache zu verwenden, fügen Sie dem Paket Microsoft.Extensions.Caching.SqlServer einen Paketverweis hinzu.

Um einen verteilten Redis-Cache zu verwenden, fügen Sie dem Paket Microsoft.Extensions.Caching.StackExchangeRedis einen Paketverweis hinzu.

Um den verteilten NCache-Cache zu verwenden, fügen Sie dem Paket NCache.Microsoft.Extensions.Caching.OpenSource einen Paketverweis hinzu.

IDistributedCache-Schnittstelle

Die IDistributedCache-Schnittstelle bietet die folgenden Methoden zum Bearbeiten von Elementen bei der Implementierung des verteilten Cache:

  • Get, GetAsync: Akzeptiert einen Zeichenfolgenschlüssel und ruft ein zwischengespeichertes Element als byte[]-Array ab, wenn es im Cache gefunden wird.
  • Set, SetAsync: Fügt dem Cache mithilfe eines Zeichenfolgenschlüssels ein Element (als byte[]-Array) hinzu.
  • Refresh, RefreshAsync: Aktualisiert ein Element im Cache auf Grundlage seines Schlüssels und setzt das gleitende Ablauftimeout (sofern vorhanden) zurück.
  • Remove, RemoveAsync: Entfernt ein Cacheelement anhand seines Zeichenfolgenschlüssels.

Einrichten verteilter Zwischenspeicherdienste

Registrieren Sie eine Implementierung von IDistributedCache in Startup.ConfigureServices. Im Framework bereitgestellte Implementierungen, die in diesem Thema beschrieben werden, umfassen:

Verteilter Speichercache

Der verteilte Speichercache (AddDistributedMemoryCache) ist eine vom Framework bereitgestellte Implementierung von IDistributedCache, die Elemente im Arbeitsspeicher speichert. Der verteilte Speichercache ist kein tatsächlich verteilter Cache. Zwischengespeicherte Elemente werden von der App-Instanz auf dem Server gespeichert, auf dem die App ausgeführt wird.

Der verteilte Speichercache ist eine nützliche Implementierung:

  • In Entwicklungs- und Testszenarien.
  • Wenn ein einzelner Server in der Produktion verwendet wird und die Arbeitsspeichernutzung kein Problem ist. Durch die Implementierung des verteilten Speichercache wird die Speicherung von Cachedaten abstrahiert. Dies ermöglicht die Implementierung einer echten verteilten Zwischenspeicherungslösung in der Zukunft, wenn mehrere Knoten oder Fehlertoleranz erforderlich werden.

Die Beispiel-App verwendet den verteilten Speichercache, wenn die App in der Entwicklungsumgebung in Startup.ConfigureServicesausgeführt wird:

services.AddDistributedMemoryCache();

Verteilter SQL Server-Cache

Die Implementierung des verteilten SQL Server-Cache (AddDistributedSqlServerCache) ermöglicht es dem verteilten Cache, eine SQL Server-Datenbank als Sicherungsspeicher zu verwenden. Um eine zwischengespeicherte SQL Server.Elementtabelle in einer SQL Server-Instanz zu erstellen, können Sie das Tool sql-cache verwenden. Das Tool erstellt eine Tabelle mit dem von Ihnen angegebenen Namen und Schema.

Erstellen Sie eine Tabelle in SQL Server, indem Sie den Befehl sql-cache create ausführen. Geben Sie die SQL Server-Instanz (Data Source), die Datenbank (Initial Catalog), das Schema (z. B. dbo) und den Tabellennamen (z. B. TestCache) an:

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

Eine Meldung wird protokolliert, um anzugeben, dass das Tool erfolgreich war:

Table and index were created successfully.

Die vom sql-cache-Tool erstellte Tabelle weist das folgende Schema auf:

SqlServer-Cache-Tabelle

Hinweis

Eine App sollte Cachewerte mithilfe einer Instanz von IDistributedCache, nicht von SqlServerCache, bearbeiten.

Die Beispiel-App implementiert SqlServerCache in einer Nicht-Entwicklungsumgebung in Startup.ConfigureServices:

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

Hinweis

ConnectionString sowie optional SchemaName und TableName werden in der Regel außerhalb der Quellcodeverwaltung gespeichert (z. B. vom Secret Manager oder in appsettings.json/appsettings.{Environment}.json-Dateien gespeichert). Die Verbindungszeichenfolge kann Anmeldeinformationen enthalten, die außerhalb der Quellcodeverwaltungssysteme aufbewahrt werden sollten.

Verteilter Redis-Cache

Redis ist ein Open Source In-Memory-Datenspeicher, der häufig als verteilter Cache verwendet wird. Sie können einen Azure Redis Cache für eine von Azure gehostete ASP.NET Core-App konfigurieren und einen Azure Redis Cache für die lokale Entwicklung verwenden.

Eine App konfiguriert die Cacheimplementierung mithilfe einer RedisCache-Instanz (AddStackExchangeRedisCache).

  1. Erstellen Sie einen Azure Cache for Redis.
  2. Kopieren Sie die primäre Verbindungszeichenfolge (StackExchange.Redis) in Configuration.
    • Lokale Entwicklung: Speichern Sie die Verbindungszeichenfolge mit Secret Manager.
    • Azure: Speichern Sie die Verbindungszeichenfolge in der App Service Configuration oder in einem anderen sicheren Speicher.

Der folgende Code aktiviert Azure Cache for Redis:

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

    services.AddRazorPages();
}

Im vorherigen Code wird davon ausgegangen, dass die primäre Verbindungszeichenfolge (StackExchange.Redis) in Configuration mit dem Schlüsselnamen MyRedisConStrgespeichert wurde.

Weitere Informationen finden Sie unter Azure Cache for Redis.

In diesem GitHub-Problem finden Sie eine Diskussion zu alternativen Ansätzen für einen lokalen Redis-Cache.

Verteilter NCache-Cache

NCache ist ein verteilter Open Source In-Memory-Cache, der nativ in .NET und .NET Core entwickelt wurde. NCache funktioniert sowohl lokal als auch als verteilter Cachecluster für eine ASP.NET Core-App, die in Azure oder auf anderen Hostingplattformen ausgeführt wird.

Informationen zum Installieren und Konfigurieren von NCache auf Ihrem lokalen Computer finden Sie unter Leitfaden mit ersten Schritten für Windows (.NET und .NET Core).

So konfigurieren Sie NCache:

  1. Installieren Sie NCache Open Source NuGet.

  2. Konfigurieren Sie den Cachecluster in client.ncconf.

  3. Fügen Sie den folgenden Code zu Startup.ConfigureServices hinzu:

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

Verwenden des verteilten Cache

Um die IDistributedCache-Schnittstelle zu verwenden, fordern Sie eine Instanz von IDistributedCache von einem beliebigen Konstruktor in der App an. Die Instanz wird durch Abhängigkeitsinjektion (Dependency Injection, DI) bereitgestellt.

Wenn die Beispiel-App gestartet wird, wird IDistributedCache in Startup.Configureeingebracht. Die aktuelle Zeit wird mit IHostApplicationLifetime zwischengespeichert (weitere Informationen finden Sie unter Generischer Host: 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);
    });

Die Beispiel-App bringt IDistributedCache zwecks Verwendung durch die Indexseite in IndexModel ein.

Jedes Mal, wenn die Indexseite geladen wird, wird der Cache auf die zwischengespeicherte Zeit in OnGetAsyncüberprüft. Wenn die zwischengespeicherte Zeit nicht abgelaufen ist, wird die Uhrzeit angezeigt. Wenn seit dem letzten Zugriff auf die zwischengespeicherte Zeit (das letzte Laden dieser Seite) 20 Sekunden verstrichen sind, wird auf der Seite Zwischengespeicherte Zeit abgelaufen angezeigt.

Aktualisieren Sie sofort die zwischengespeicherte Zeit auf die aktuelle Zeit, indem Sie die Schaltfläche Zwischengespeicherte Zeit zurücksetzen auswählen. Die Schaltfläche löst die Handlermethode OnPostResetCachedTime aus.

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

Hinweis

Es ist nicht erforderlich, eine Singleton- oder bereichsbezogene Lebensdauer für IDistributedCache-Instanzen (zumindest für die integrierten Implementierungen) zu verwenden.

Sie können zudem eine IDistributedCache-Instanz überall dort erstellen, wo Sie anstelle von DI eine Instanz benötigen, aber das Erstellen einer Instanz im Code kann das Testen Ihres Codes erschweren und gegen das Prinzip der expliziten Abhängigkeiten verstoßen.

Empfehlungen

Bei der Entscheidung, welche Implementierung von IDistributedCache für Ihre App am besten geeignet ist, sollten Sie Folgendes berücksichtigen:

  • Vorhandene Infrastruktur
  • Leistungsanforderungen
  • Kosten
  • Teamerfahrung

Zwischenspeicherlösungen basieren in der Regel auf In-Memory-Speicher, um einen schnellen Abruf von zwischengespeicherten Daten zu ermöglichen. Der Arbeitsspeicher ist jedoch nur eine begrenzte Ressource und seine Erweiterung kostspielig. Speichern Sie nur häufig verwendete Daten in einem Cache.

Im Allgemeinen bietet ein Redis-Cache einen höheren Durchsatz und eine geringere Latenzzeit als ein SQL Server-Cache. Es ist jedoch in der Regel ein Benchmarking erforderlich, um die Leistungsmerkmale von Zwischenspeicherungsstrategien zu bestimmen.

Wenn SQL Server als verteilter Cachesicherungsspeicher verwendet wird, kann sich die Verwendung derselben Datenbank für den Cache und die normale Datenspeicherung der App und das Abrufen negativ auf die Leistung beider auswirken. Es wird empfohlen, eine dedizierte SQL Server-Instanz für den verteilten Cachesicherungsspeicher zu verwenden.

Zusätzliche Ressourcen