Bibliothèque HybridCache dans ASP.NET Core
Important
Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.
Cet article explique comment configurer et utiliser la bibliothèque HybridCache
dans une application ASP.NET Core. Pour accéder à une présentation de la bibliothèque, consultez la section HybridCache
de la vue d’ensemble de la mise en cache.
Obtenir la bibliothèque
Installez le package Microsoft.Extensions.Caching.Hybrid
.
dotnet add package Microsoft.Extensions.Caching.Hybrid --prerelease
Enregistrer le service
Ajoutez le service HybridCache
au conteneur d’injection de dépendances en appelant AddHybridCache
:
// Add services to the container.
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddAuthorization();
builder.Services.AddHybridCache();
Le code précédent inscrit le service HybridCache
avec les options par défaut. L’API d’inscription peut également configurer les options et la sérialisation.
Obtenir et stocker des entrées de cache
Le service HybridCache
fournit une méthode GetOrCreateAsync
avec deux surcharges, qui acceptent une clé et :
- Une méthode de fabrique.
- Un état et une méthode de fabrique.
La méthode utilise la clé pour tenter de récupérer l’objet dans le cache principal. Si l’élément est introuvable dans le cache principal (non-correspondance dans le cache), elle vérifie le cache secondaire, le cas échéant. Si les données sont introuvables également à cet emplacement (autre non-correspondance dans le cache), elle appelle la méthode de fabrique pour obtenir l’objet à partir de la source de données. Elle stocke ensuite l’objet dans les caches principal et secondaire. La méthode de fabrique n’est jamais appelée si l’objet est trouvé dans le cache principal ou secondaire (correspondance dans le cache).
Le service HybridCache
vérifie qu’un seul appelant simultané pour une clé donnée exécute la méthode de fabrique, et que tous les autres appelants attendent le résultat de cette exécution. Le CancellationToken
passé à GetOrCreateAsync
représente l’annulation combinée de tous les appelants simultanés.
Surcharge principale de GetOrCreateAsync
La surcharge sans état de GetOrCreateAsync
est recommandée pour la plupart des scénarios. Le code permettant de l’appeler est relativement simple. Voici un exemple :
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),
token: token
);
}
public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
{
string someInfo = $"someinfo-{name}-{id}";
return someInfo;
}
}
Surcharge alternative de GetOrCreateAsync
La surcharge alternative peut réduire la charge de traitement liée aux variables capturées et aux rappels par instance, mais au prix d’un code plus complexe. Dans la plupart des scénarios, l’augmentation des performances ne l’emporte pas sur la complexité du code. Voici un exemple d’utilisation de la surcharge alternative :
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),
token: token
);
}
public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
{
string someInfo = $"someinfo-{name}-{id}";
return someInfo;
}
}
Méthode SetAsync
Dans de nombreux scénarios, GetOrCreateAsync
est la seule API nécessaire. Toutefois, HybridCache
dispose également de SetAsync
pour stocker un objet dans le cache sans essayer de le récupérer au préalable.
Supprimer les entrées de cache non expirées
Quand les données sous-jacentes des entrées de cache changent avant leur expiration, vous pouvez supprimer explicitement ces entrées. Les entrées à supprimer peuvent être spécifiées par clé. Quand une entrée est supprimée, elle est retirée des caches principal et secondaire.
Supprimer par clé
Les méthodes suivantes prennent en charge la suppression des entrées de cache par clé :
RemoveKeyAsync
RemoveKeysAsync
Remarque : Celles-ci seront remplacées par RemoveByKeyAsync
et RemoveByKeysAsync
à l’avenir.
Options
La méthode AddHybridCache
peut être utilisée pour la configuration globale par défaut. L’exemple suivant montre comment configurer certaines des options disponibles :
// 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)
};
});
La méthode GetOrCreateAsync
peut également accepter un objet HybridCacheEntryOptions
pour remplacer les valeurs par défaut globales d’une entrée de cache spécifique. Voici un exemple :
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,
token: token
);
}
public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
{
string someInfo = $"someinfo-{name}-{id}";
return someInfo;
}
}
Pour plus d’informations sur les options, consultez le code source :
- HybridCacheOptions, classe.
- HybridCacheEntryOptions, classe.
Limites
Les propriétés suivantes de HybridCacheOptions
vous permettent de configurer des limites qui s’appliquent à toutes les entrées de cache :
- MaximumPayloadBytes : taille maximale d’une entrée de cache. La valeur par défaut est de 1 Mo. Les tentatives de stockage de valeurs dépassant cette taille sont journalisées, et aucune valeur n’est stockée dans le cache.
- MaximumKeyLength : longueur maximale d’une clé de cache. La valeur par défaut est de 1 024 caractères. Les tentatives de stockage de valeurs dépassant cette taille sont journalisées, et aucune valeur n’est stockée dans le cache.
Sérialisation
L’utilisation d’un cache secondaire hors processus nécessite une sérialisation. La sérialisation est configurée dans le cadre de l’inscription du service HybridCache
. Les sérialiseurs spécifiques à un type ainsi que les sérialiseurs à usage général peuvent être configurés via les méthodes WithSerializer
et WithSerializerFactory
, chaînées à partir de l’appel de AddHybridCache
. Par défaut, la bibliothèque gère string
et byte[]
de manière interne, et utilise System.Text.Json
pour tout le reste. HybridCache
peut également utiliser d’autres sérialiseurs, par exemple protobuf ou XML.
L’exemple suivant configure le service pour qu’il utilise un sérialiseur protobuf spécifique au type :
// 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)
};
}).WithSerializer<SomeProtobufMessage,
GoogleProtobufSerializer<SomeProtobufMessage>>();
L’exemple suivant configure le service pour qu’il utilise un sérialiseur protobuf à usage général, capable de gérer de nombreux types protobuf :
// 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)
};
}).WithSerializerFactory<GoogleProtobufSerializerFactory>();
Le cache secondaire nécessite un magasin de données, par exemple Redis ou SqlServer. Pour utiliser Azure Cache pour Redis, par exemple :
Installez le package
Microsoft.Extensions.Caching.StackExchangeRedis
.Créez une instance d’Azure Cache pour Redis.
Obtenez une chaîne de connexion qui se connecte à l’instance de Redis. Recherchez la chaîne de connexion en sélectionnant Afficher les clés d’accès dans la page Vue d’ensemble du portail Azure.
Stockez la chaîne de connexion dans la configuration de l’application. Par exemple, utilisez un fichier de secrets utilisateur qui ressemble au code JSON suivant, et spécifiez la chaîne de connexion dans la section
ConnectionStrings
. Remplacez<the connection string>
par la chaîne de connexion réelle :{ "ConnectionStrings": { "RedisConnectionString": "<the connection string>" } }
Inscrivez l’implémentation de
IDistributedCache
fournie par le package Redis dans le conteneur d’injection de dépendances. Pour ce faire, appelezAddStackExchangeRedisCache
, et passez la chaîne de connexion. Par exemple :builder.Services.AddStackExchangeRedisCache(options => { options.Configuration = builder.Configuration.GetConnectionString("RedisConnectionString"); });
L’implémentation Redis de
IDistributedCache
est désormais disponible dans le conteneur d’injection de dépendances de l’application.HybridCache
s’en sert en tant que cache secondaire, et utilise pour cela le sérialiseur configuré.
Pour plus d’informations, consultez l’exemple d’application de sérialisation HybridCache.
Stockage du cache
Par défaut, HybridCache
utilise MemoryCache pour le stockage dans le cache principal. Les entrées de cache sont stockées in-process. Ainsi, chaque serveur dispose d’un cache distinct, qui est perdu à chaque redémarrage du processus serveur. Pour le stockage hors processus secondaire, par exemple Redis ou SQL Server, HybridCache
utilise l’implémentation configurée de IDistributedCache
, le cas échéant. Toutefois, même sans l’implémentation de IDistributedCache
, le service HybridCache
fournit toujours une mise en cache in-process et une protection contre les requêtes simultanées en grand nombre.
Optimiser les performances
Pour optimiser les performances, configurez HybridCache
afin de réutiliser les objets et d’éviter les allocations de byte[]
.
Réutiliser des objets
Dans le code existant classique qui utilise IDistributedCache
, chaque récupération d’un objet à partir du cache entraîne une désérialisation. Ce comportement signifie que chaque appelant simultané obtient une instance distincte de l’objet, qui ne peut pas interagir avec d’autres instances. Il en résulte une cohérence de thread, car il n’existe aucun risque de modifications simultanées sur la même instance d’objet.
Dans la mesure où une grande partie de l’utilisation de HybridCache
est adaptée à partir du code IDistributedCache
existant, HybridCache
conserve ce comportement par défaut pour éviter d’introduire des bogues de concurrence. Toutefois, les objets sont intrinsèquement thread-safe si :
- Leurs types sont immuables.
- Le code ne les modifie pas.
Dans ce genre de situation, indiquez à HybridCache
que les instances peuvent être réutilisées de manière sécurisée en :
- Marquant le type en tant que
sealed
. Le mot clésealed
en C# signifie que la classe ne peut pas être héritée. - Appliquant l’attribut
[ImmutableObject(true)]
au type. L’attribut[ImmutableObject(true)]
indique que l’état de l’objet ne peut pas être changé après sa création.
En réutilisant des instances, HybridCache
peut réduire la charge de traitement des allocations de processeur et d’objets associées à la désérialisation par appel. Cela peut entraîner une amélioration des performances dans les scénarios où les objets mis en cache sont volumineux ou utilisés fréquemment.
Éviter les allocations de byte[]
HybridCache
fournit également des API facultatives pour les implémentations de IDistributedCache
, afin d’éviter les allocations de byte[]
. Cette fonctionnalité est implémentée par les préversions des packages Microsoft.Extensions.Caching.StackExchangeRedis
et Microsoft.Extensions.Caching.SqlServer
. Pour plus d’informations, consultez IBufferDistributedCache. Voici les commandes CLI .NET pour installer les packages :
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis --prerelease
dotnet add package Microsoft.Extensions.Caching.SqlServer --prerelease
Implémentations personnalisées de HybridCache
Une implémentation concrète de la classe abstraite HybridCache
est incluse dans l’infrastructure partagée, et est fournie via une injection de dépendances. Toutefois, les développeurs sont invités à fournir des implémentations personnalisées de l’API.
Compatibilité
La bibliothèque prend en charge les runtimes .NET plus anciens, jusqu’à .NET Framework 4.7.2 et .NET Standard 2.0.
Ressources supplémentaires
Pour plus d’informations sur HybridCache
, consultez les ressources suivantes :
- Problème GitHub dotnet/aspnetcore #54647.
- Code source de
HybridCache
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de l’année 2024, nous abandonnerons progressivement le mécanisme de retour d’information GitHub Issues pour le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultez :Soumettre et afficher des commentaires pour