Megosztás a következőn keresztül:


HybridCache-kódtár a ASP.NET Core-ban

Ez a cikk bemutatja, hogyan konfigurálhatja és használhatja a HybridCache-kódtárat egy ASP.NET Core-alkalmazásban. A könyvtárral való megismerkedéshez lásd: HybridCache szakaszában.

A könyvtár lekérése

Telepítse a Microsoft.Extensions.Caching.Hybrid csomagot.

dotnet add package Microsoft.Extensions.Caching.Hybrid

A szolgáltatás regisztrálása

Adja hozzá a HybridCache szolgáltatást a függőséginjektáló (DI) tárolóhoz AddHybridCachemeghívásával:

// Add services to the container.
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddAuthorization();

builder.Services.AddHybridCache();

Az előző kód az alapértelmezett beállításokkal regisztrálja a HybridCache szolgáltatást. A regisztrációs API beállításokat és szerializálást is konfigurálhat.

Gyorsítótárbejegyzések lekérése és tárolása

A HybridCache szolgáltatás két túlterheléssel rendelkező GetOrCreateAsync metódust biztosít, amely egy kulcsot és egy következőt használ:

  • Egy gyári módszer.
  • Állapot és egy gyári metódus.

A metódus a kulccsal próbálja lekérni az objektumot az elsődleges gyorsítótárból. Ha az elem nem található az elsődleges gyorsítótárban (a gyorsítótár hiányzik), akkor ellenőrzi a másodlagos gyorsítótárat, ha van konfigurálva. Ha nem találja ott az adatokat (egy másik gyorsítótár hiányzik), meghívja a gyári metódust, hogy lekérje az objektumot az adatforrásból. Ezután az objektumot elsődleges és másodlagos gyorsítótárakban is tárolja. A gyári metódus soha nem lesz meghívva, ha az objektum az elsődleges vagy másodlagos gyorsítótárban található (gyorsítótár-találat).

A HybridCache szolgáltatás biztosítja, hogy egy adott kulcshoz csak egy egyidejű hívó hívja meg a gyári metódust, és az összes többi hívó várja meg a hívás eredményét. A CancellationToken átadott GetOrCreateAsync az összes egyidejű hívó együttes lemondását jelenti.

A fő GetOrCreateAsync túlterhelés

A GetOrCreateAsync állapot nélküli túlterhelése a legtöbb forgatókönyv esetében ajánlott. A hívandó kód viszonylag egyszerű. Íme egy példa:

public class SomeService(HybridCache cache)
{
    private HybridCache _cache = cache;

    public async Task<string> GetSomeInfoAsync(string name, int id, CancellationToken token = default)
    {
        return await _cache.GetOrCreateAsync(
            $"{name}-{id}", // Unique key to the cache entry
            async cancel => await GetDataFromTheSourceAsync(name, id, cancel),
            cancellationToken: token
        );
    }

    public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
    {
        string someInfo = $"someinfo-{name}-{id}";
        return someInfo;
    }
}

Gyorsítótárkulcsra vonatkozó útmutató

A key, amely a GetOrCreateAsync-hez kerül, egyedileg azonosítania kell a gyorsítótárazott adatokat.

  • Az adatok forrásból való lekéréséhez használt azonosítóértékeket tekintve.
  • Az alkalmazásban tárolt egyéb gyorsítótárazott adatok tekintetében.

Az egyediség mindkét típusát általában úgy biztosítják, hogy különböző részeket szövegösszefűzéssel összekapcsolnak egyetlen kulcstömeggé. Például:

cache.GetOrCreateAsync($"/orders/{region}/{orderId}", ...);

Vagy

cache.GetOrCreateAsync($"user_prefs_{userId}", ...);

A hívó felelőssége annak biztosítása, hogy egy kulcsséma érvényes legyen, és ne okozzon zavart az adatokban.

Kerülje a külső felhasználói bemenet közvetlen használatát a gyorsítótárkulcsokban. Például ne használjon nyers sztringeket a felhasználói felületekről gyorsítótárkulcsként. Ezzel biztonsági kockázatoknak teheti ki az alkalmazást, például a gyorsítótár véletlenszerű vagy értelmetlen kulcsokkal való elárasztása által okozott jogosulatlan hozzáférést vagy szolgáltatásmegtagadási támadásokat. Az előző érvényes példákban a rendelési és felhasználói beállítások adatai egyértelműen elkülönülnek egymástól, és megbízható azonosítókat használnak:

  • orderid és userId belsőleg generált azonosítók.
  • region az ismert régiók előre definiált listájából származó szám vagy sztring lehet.

A / vagy _ tokeneknek nincs jelentősége. A rendszer a teljes kulcsértéket átlátszatlan azonosító sztringként kezeli. Ebben az esetben kihagyhatja a / és a _, és nem változtat a gyorsítótár működésén, de a kétértelműség elkerülése érdekében általában elválasztójelet használnak – például $"order{customerId}{orderId}" zavart okozhat a következők között:

  • customerId 42 és orderId 123
  • customerId 421 orderId 23-mal

Mindkét fenti példa létrehozza a gyorsítótárkulcsot order42123.

Ez az útmutató egyformán vonatkozik minden string-alapú gyorsítótár API-ra, például HybridCache, IDistributedCacheés IMemoryCache.

Figyelje meg, hogy a beágyazott, interpolált sztring szintaxis ($"..." az előző érvényes kulcsértelmezések példáiban) közvetlenül a GetOrCreateAsync hívásban megtalálható. Ez a szintaxis a HybridCachehasználata esetén ajánlott, mivel olyan tervezett jövőbeli fejlesztéseket tesz lehetővé, amelyek elkerülik a kulcshoz tartozó string lefoglalásának szükségességét számos forgatókönyvben.

További fontos szempontok

  • A kulcsok érvényes maximális hosszúságra korlátozhatók. Az alapértelmezett HybridCache implementáció (AddHybridCache(...)) például alapértelmezés szerint 1024 karakterre korlátozza a kulcsokat. Ez a szám HybridCacheOptions.MaximumKeyLengthkeresztül konfigurálható, és a hosszabb kulcsok megkerülik a gyorsítótár-mechanizmusokat, hogy megakadályozzák a telítettséget.
  • A kulcsoknak érvényes Unicode-szekvenciáknak kell lenniük. Ha a rendszer érvénytelen Unicode-sorozatokat ad át, a viselkedés nincs meghatározva.
  • Ha folyamaton kívüli másodlagos gyorsítótárat használ, például IDistributedCachea háttérrendszer implementációja további korlátozásokat írhat elő. Hipotetikus példaként egy adott háttérrendszer a kis- és nagybetűkre érzéketlen kulcslogikát használhatja. Az alapértelmezett HybridCache (via AddHybridCache(...)) felismeri ezt a forgatókönyvet a megzavarási támadások vagy az aliastámadások megelőzése érdekében (bitenkénti karakterlánc-egyenlőség használatával). Ez a forgatókönyv azonban továbbra is azt eredményezheti, hogy az ütköző kulcsok a vártnál hamarabb felülíródnak vagy kiüríthetők.

Az alternatív GetOrCreateAsync túlterhelési lehetőség

Az alternatív túlterhelés csökkentheti az olyan változók némi terhelését, amelyek módon vannak rögzítve, valamint a példányonkénti visszahívások terhelését, de az összetettebb kód rovására. A legtöbb forgatókönyv esetében a teljesítménynövekedés nem haladják meg a kód összetettségét. Íme egy példa, amely az alternatív túlterhelést használja:

public class SomeService(HybridCache cache)
{
    private HybridCache _cache = cache;

    public async Task<string> GetSomeInfoAsync(string name, int id, CancellationToken token = default)
    {
        return await _cache.GetOrCreateAsync(
            $"{name}-{id}", // Unique key to the cache entry
            (name, id, obj: this),
            static async (state, token) =>
            await state.obj.GetDataFromTheSourceAsync(state.name, state.id, token),
            cancellationToken: token
        );
    }

    public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
    {
        string someInfo = $"someinfo-{name}-{id}";
        return someInfo;
    }
}

A SetAsync metódus

Sok esetben a GetOrCreateAsync az egyetlen szükséges API. HybridCache azonban SetAsync is tárolhat egy objektumot a gyorsítótárban anélkül, hogy először megpróbálná lekérni.

Gyorsítótárbejegyzések eltávolítása kulcs szerint

Ha a gyorsítótár-bejegyzés alapjául szolgáló adatok a lejárat előtt megváltoznak, távolítsa el a bejegyzést explicit módon, ha meghívja RemoveAsync a bejegyzés kulcsával. A túlterhelés lehetővé teszi a kulcsértékek gyűjteményének megadását.

Egy bejegyzés eltávolításakor az elsődleges és a másodlagos gyorsítótárból is törlődik.

Gyorsítótárbejegyzések eltávolítása címke szerint

A címkék a gyorsítótár bejegyzéseinek csoportosítására és közös érvénytelenítésére használhatók.

Adja meg a címkéket GetOrCreateAsynchívásához, ahogyan az alábbi példában látható:

public class SomeService(HybridCache cache)
{
    private HybridCache _cache = cache;

    public async Task<string> GetSomeInfoAsync(string name, int id, CancellationToken token = default)
    {
        var tags = new List<string> { "tag1", "tag2", "tag3" };
        var entryOptions = new HybridCacheEntryOptions
        {
            Expiration = TimeSpan.FromMinutes(1),
            LocalCacheExpiration = TimeSpan.FromMinutes(1)
        };
        return await _cache.GetOrCreateAsync(
            $"{name}-{id}", // Unique key to the cache entry
            async cancel => await GetDataFromTheSourceAsync(name, id, cancel),
            entryOptions,
            tags,
            cancellationToken: token
        );
    }
    
    public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
    {
        string someInfo = $"someinfo-{name}-{id}";
        return someInfo;
    }
}

Távolítsa el egy adott címke összes bejegyzését a címkeértékkel rendelkező RemoveByTagAsync meghívásával. A túlterhelés lehetővé teszi a címkeértékek gyűjteményének megadását.

A címkék fogalmának közvetlen támogatása sincs IMemoryCacheIDistributedCache , ezért a címkealapú érvénytelenítés csak logikai művelet. Nem távolítja el aktívan az értékeket sem a helyi, sem az elosztott gyorsítótárból. Ehelyett biztosítja, hogy amikor az ilyen címkékkel rendelkező adatokat fogadják, azokat mind a helyi, mind a távoli gyorsítótárból származó gyorsítótár-kihagyásként kezelik. Az értékek a konfigurált élettartamtól függően IMemoryCacheIDistributedCache a szokásos módon lejárnak.

Az összes gyorsítótár-bejegyzés eltávolítása

A csillagcímke (*) helyettesítő karakterként van fenntartva, és nem engedélyezett az egyes értékekkel szemben. A hívás RemoveByTagAsync("*") az összesHybridCache adatot érvényteleníti, még a címkéket nem tartalmazó adatokat is. Az egyes címkékhez hasonlóan ez is logikai művelet, és az egyes értékek továbbra is léteznek, amíg azok természetes módon le nem járnak. A glob sablon szerinti egyezések nem támogatottak. Például nem használhatja a RemoveByTagAsync("foo*")-t arra, hogy mindent eltávolítson, ami foo-nel kezdődik.

További címkefeltételek

  • A rendszer nem korlátozza a használható címkék számát, de a nagy méretű címkék negatív hatással lehetnek a teljesítményre.
  • A címkék nem lehetnek üresek, nem tartalmazhatnak csak szóközt, és nem lehetnek fenntartott értékűek *.

Beállítások

A AddHybridCache metódus használható a globális alapértelmezett beállítások konfigurálásához. Az alábbi példa bemutatja, hogyan konfigurálhat néhányat az elérhető lehetőségek közül:

// Add services to the container.
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthorization();

builder.Services.AddHybridCache(options =>
    {
        options.MaximumPayloadBytes = 1024 * 1024;
        options.MaximumKeyLength = 1024;
        options.DefaultEntryOptions = new HybridCacheEntryOptions
        {
            Expiration = TimeSpan.FromMinutes(5),
            LocalCacheExpiration = TimeSpan.FromMinutes(5)
        };
    });

A GetOrCreateAsync metódus egy HybridCacheEntryOptions objektumot is igénybe vehet egy adott gyorsítótár-bejegyzés globális alapértelmezett értékének felülbírálásához. Íme egy példa:

public class SomeService(HybridCache cache)
{
    private HybridCache _cache = cache;

    public async Task<string> GetSomeInfoAsync(string name, int id, CancellationToken token = default)
    {
        var tags = new List<string> { "tag1", "tag2", "tag3" };
        var entryOptions = new HybridCacheEntryOptions
        {
            Expiration = TimeSpan.FromMinutes(1),
            LocalCacheExpiration = TimeSpan.FromMinutes(1)
        };
        return await _cache.GetOrCreateAsync(
            $"{name}-{id}", // Unique key to the cache entry
            async cancel => await GetDataFromTheSourceAsync(name, id, cancel),
            entryOptions,
            tags,
            cancellationToken: token
        );
    }
    
    public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
    {
        string someInfo = $"someinfo-{name}-{id}";
        return someInfo;
    }
}

A lehetőségekről további információt a forráskódban talál:

Határok

A HybridCacheOptions alábbi tulajdonságai lehetővé teszik az összes gyorsítótár-bejegyzésre vonatkozó korlátok konfigurálását:

  • MaximumPayloadBytes – Gyorsítótár-bejegyzés maximális mérete. Az alapértelmezett érték 1 MB. A rendszer naplózza az ilyen méretű értékek tárolására tett kísérleteket, és az érték nem a gyorsítótárban van tárolva.
  • MaximumKeyLength – A gyorsítótárkulcs maximális hossza. Az alapértelmezett érték 1024 karakter. A rendszer naplózza az ilyen méretű értékek tárolására tett kísérleteket, és az érték nem a gyorsítótárban van tárolva.

Szerializáció

A másodlagos, folyamaton kívüli gyorsítótár használatához szerializálás szükséges. A szerializálás a HybridCache szolgáltatás regisztrálásának részeként van konfigurálva. A típusspecifikus és általános célú szerializálók a AddSerializer és AddSerializerFactory metódusokkal konfigurálhatók, a AddHybridCache hívástól láncolt módon. Alapértelmezés szerint a kódtár belsőleg kezeli a string és a byte[], és minden máshoz System.Text.Json használ. HybridCache más szerializálókat is használhat, például protobuf vagy XML.

Az alábbi példa egy típusspecifikus protobuf szerializáló használatára konfigurálja a szolgáltatást:

// Add services to the container.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthorization();

builder.Services.AddHybridCache(options =>
    {
        options.DefaultEntryOptions = new HybridCacheEntryOptions
        {
            Expiration = TimeSpan.FromSeconds(10),
            LocalCacheExpiration = TimeSpan.FromSeconds(5)
        };
    }).AddSerializer<SomeProtobufMessage, 
        GoogleProtobufSerializer<SomeProtobufMessage>>();

Az alábbi példa egy általános célú protobuf szerializáló használatára konfigurálja a szolgáltatást, amely számos protobuf-típust képes kezelni:

// Add services to the container.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthorization();

builder.Services.AddHybridCache(options =>
{
    options.DefaultEntryOptions = new HybridCacheEntryOptions
    {
        Expiration = TimeSpan.FromSeconds(10),
        LocalCacheExpiration = TimeSpan.FromSeconds(5)
    };
}).AddSerializerFactory<GoogleProtobufSerializerFactory>();

A másodlagos gyorsítótárhoz szükség van egy adattárra, például a Redisre vagy az SqlServerre. A Azure Cache for Redishasználatához, például:

  • Telepítse a Microsoft.Extensions.Caching.StackExchangeRedis csomagot.

  • Hozzon létre egy Azure Cache for Redis-példányt.

  • Szerezze be a Redis-példányhoz csatlakozó kapcsolati karakterláncot. A kapcsolati sztring megkereséséhez válassza a Hozzáférési kulcsok megjelenítése lehetőséget az Azure Portal Áttekintés lapján.

  • Tárolja a kapcsolati sztringet az alkalmazás konfigurációjában. Használjon például egy felhasználói titkos kódfájlt, amely az alábbi JSON-fájlhoz hasonlóan néz ki, és a kapcsolati sztring a ConnectionStrings szakaszban található. Cserélje le <the connection string> a tényleges kapcsolati sztringre:

    {
      "ConnectionStrings": {
        "RedisConnectionString": "<the connection string>"
      }
    }
    
  • Regisztrálja a Redis-csomag által biztosított IDistributedCache implementációt a DI rendszerében. Ehhez hívja meg AddStackExchangeRedisCache, és adja meg a kapcsolati sztringet. Például:

    builder.Services.AddStackExchangeRedisCache(options =>
    {
        options.Configuration = 
            builder.Configuration.GetConnectionString("RedisConnectionString");
    });
    
  • A Redis IDistributedCache implementáció már elérhető az alkalmazás DI-tárolójából. HybridCache másodlagos gyorsítótárként használja, és a hozzá konfigurált szerializálót használja.

További információ: HybridCache szerializálási mintaalkalmazás.

Gyorsítótár-tároló

Alapértelmezés szerint HybridCacheMemoryCache használ az elsődleges gyorsítótár-tárolóhoz. A gyorsítótárbejegyzések tárolása folyamatban történik, így minden kiszolgáló külön gyorsítótárral rendelkezik, amely a kiszolgálói folyamat újraindításakor elveszik. A másodlagos, folyamaton kívüli tárolás, mint például a Redis vagy az SQL Server esetében, a HybridCachekonfiguráció szerint megvalósított IDistributedCache megoldást használja, ha van ilyen. De még IDistributedCacheimplementáció nélkül is a HybridCache szolgáltatás továbbra is biztosítja a folyamaton belüli gyorsítótárazást és a tömeges hozzáférés védelmét.

Jegyzet

Ha kulcs vagy címkék alapján érvényteleníti a gyorsítótár-bejegyzéseket, azok érvénytelenítve lesznek az aktuális kiszolgálón és a másodlagos folyamaton kívüli tárolóban. Más kiszolgálók memóriabeli gyorsítótára azonban nincs érintve.

Teljesítmény optimalizálása

A teljesítmény optimalizálásához konfigurálja a HybridCache az objektumok újrafelhasználására és a byte[] lefoglalások elkerülésére.

Objektumok újrafelhasználása

A példányok újrafelhasználásával HybridCache csökkentheti a hívásonkénti deszerializálással társított processzor- és objektumfoglalások többletterhelését. Ez teljesítménybeli javuláshoz vezethet olyan esetekben, amikor a gyorsítótárazott objektumok nagy méretűek vagy gyakran érhetők el.

A IDistributedCachehasználó tipikus meglévő kódban egy objektum gyorsítótárból való minden lekérése deszerializálást eredményez. Ez a viselkedés azt jelenti, hogy minden egyidejű hívó külön példányt kap az objektumból, amely nem tud más példányokkal kommunikálni. Az eredmény a szálbiztonság, mivel nem áll fenn az ugyanazon objektumpéldány egyidejű módosításának kockázata.

Mivel sok HybridCache használat a meglévő IDistributedCache kódból lesz adaptálva, HybridCache alapértelmezés szerint megőrzi ezt a viselkedést, hogy elkerülje az egyidejűségi hibák bevezetését. Az objektumok azonban eredendően szálbiztosak, ha:

  • Nem módosítható típusok.
  • A kód nem módosítja őket.

Ilyen esetekben tájékoztassa HybridCache arról, hogy biztonságos a példányok újrafelhasználása az alábbi módosítások legalább egyikének végrehajtásával:

  • A típus megjelölése sealed. A C# sealed kulcsszó azt jelenti, hogy az osztály nem örökölhető.
  • A [ImmutableObject(true)] attribútum alkalmazása a típusra. A [ImmutableObject(true)] attribútum azt jelzi, hogy az objektum állapota nem módosítható a létrehozása után.

Kerüld el a byte[] erőforrások lefoglalását

HybridCache opcionális API-kat is biztosít IDistributedCache implementációkhoz a byte[] lefoglalások elkerülése érdekében. Ezt a funkciót a Microsoft.Extensions.Caching.StackExchangeRedis és Microsoft.Extensions.Caching.SqlServer csomagok előzetes verziói implementálják. További információ: IBufferDistributedCache. A csomagok telepítéséhez a .NET CLI-parancsok a következők:

dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis
dotnet add package Microsoft.Extensions.Caching.SqlServer

Egyéni HybridCache-implementációk

A HybridCache absztrakt osztály konkrét implementációja szerepel a közös keretrendszerben, és függőséginjektáláson keresztül történik. A fejlesztők szívesen készítenek vagy használnak egyéni API implementációkat, például FusionCache.

Hibrid gyorsítótár használata natív AOT használatával

A következő natív AOT-specifikus szempontok vonatkoznak a következőkre HybridCache:

  • Szerializálás

    A natív AOT nem támogatja a futásidejű tükröződésalapú szerializálást. Ha egyéni típusokat szeretne gyorsítótárazni, forrásgenerátorokat kell használnia, vagy explicit módon AOT-kompatibilis szerializálókat kell konfigurálnia, például System.Text.Json által végzett forrásgenerálást. HybridCache még fejlesztés alatt áll, és az AOT használatának egyszerűsítése kiemelt fontosságú a fejlesztés szempontjából. További információért lásd a pull requestet dotnet/extensions#6475

  • Körülvágás

    Győződjön meg arról, hogy a gyorsítótárazott összes típusra olyan módon hivatkozik, amely megakadályozza, hogy az AOT-fordító eltávolítsa őket. A forrásgenerátorok szerializáláshoz való használata segít ebben a követelményben. További információkért lásd: ASP.NET Core támogatása a Natív AOT-hoz.

Ha helyesen állítja be a szerializálást és a vágást, ugyanúgy viselkedik a natív AOT-ban, HybridCache mint a normál ASP.NET Core-alkalmazásokban.

Kompatibilitás

A HybridCache kódtár támogatja a régebbi .NET-futtatókörnyezeteket, a .NET-keretrendszer 4.7.2-s és .NET Standard 2.0-s verziójára.

További erőforrások

További információ: forráskód HybridCache