Fermer

novembre 30, 2020

Mise en cache des couches de service dans Episerver


Lors de la création d'applications Web hautement performantes, il est toujours important de tenir compte de votre stratégie de mise en cache. Il y a certaines choses génériques que vous pouvez faire pour rendre votre site Web global plus rapide (comme la définition de stratégies de cache côté client efficaces ), mais souvent, un piège de performances bien négligé implique de faire trop d'appels d'API. Heureusement, La mise en cache d'objets d'Episerver peut vous aider à éviter ce piège.

La mise en cache des opérations coûteuses

Imaginez un scénario dans lequel vous devez rechercher des données à partir d'un système de back-office (produits, prix, emplacements, critiques… peu importe). Les données sont exposées en tant que point de terminaison REST et acceptent un certain nombre de paramètres de requête pour récupérer diverses tranches de données. Ceci est assez courant dans l'architecture Web et constitue l'un des sommets d'une expérience Web moderne et riche. Souvent, nous intégrons nos systèmes avec la «colle de couche de service» pour éviter les architectures monolithiques, mais si nous faisons cela mal, nous pouvons avoir des impacts massifs sur les performances.

Prenons l'exemple des revues. Supposons que j'ai une page de détails sur le produit et que les avis soient affichés au bas de cette page sous la pliure. Chaque fois que la page de détails du produit se charge, les avis doivent également être récupérés et chargés. Ces critiques peuvent être ajoutées ou chargées lors du chargement initial de la page – le résultat est toujours le même: la page n'est pas complètement chargée tant que les critiques ne sont pas chargées.

Par exemple, vous pouvez avoir un service simple comme celui-ci:

 interface IReviewService
{
  List  FetchReviewsFor (chaîne productId);
} 

Or, l'implémentation de ce service implique probablement une opération coûteuse. Il peut utiliser HttpClient ou RestSharp pour récupérer des critiques à partir d'une API, elles pourraient être extraites d'une base de données, etc. L'implémentation réelle n'a pas d'importance, alors je l'ai simulée à des fins de démonstration:

 List  FetchReviewsFor (chaîne productId)
{
    Liste  retVal = nouvelle liste  ();

    retVal = ...; // logique ici pour lire depuis un système externe

    return retVal;
} 

 SAS IDC Episerver Commerce Guide

Le problème est que cette opération peut prendre un certain temps à s'exécuter et que cette exécution peut bloquer le thread appelant. Bien sûr, nous pourrions l'implémenter de manière asynchrone, mais cela n'affecte pas la vitesse réelle de votre page si elle est appelée au moment du rendu de la page. De plus, notre implémentation n'est pas très tolérante aux pannes, car les pannes dans le système de stockage d'examen sous-jacent déclencheront des pannes pour toute personne appelant cette méthode. C'est là qu'une couche de mise en cache devient vraiment utile.

L'implémentation cible

Imaginez si nous pouvions écrire le code ci-dessus comme ceci:

 List  FetchReviewsFor (string productId)
{
    var cacheKey = $ "reviews-for- {productId}";

    List  retVal = _cacheService.Get <List > (cacheKey);

    if (retVal == null) {
       retVal = ...; // logique ici pour lire depuis un système externe

       _cacheService.Insert (cacheKey, retVal);
    }

    return retVal;
} 

Dans cette logique mise à jour, nous essayons d'abord de récupérer une liste d'objets de révision à partir de notre cache en mémoire. Si nous les trouvons, nous les renvoyons du cache. Si nous ne les trouvons pas, nous les récupérons à la source et mettons en cache les résultats pour le prochain appelant. On suppose ici implicitement que nous n’avons pas besoin de données d’examen pour être toujours à jour et que le cache finira par «se vider de lui-même». Alors, comment pouvons-nous mettre la main sur cet objet spécial _cacheService ?

Pour y parvenir, nous pouvons créer une façade autour du natif d'Epi IObjectInstanceCache et injecter ce wrapper en tant que dépendance dans nos services . Une bonne implémentation de point de départ ressemble à ceci:

 public class CacheService: ICacheService
{
    private IObjectInstanceCache _cache;

    chaîne de const privée MASTER_KEY = "mysite-master-key";

    CacheManager public (cache IObjectInstanceCache)
    {
        _cache = cache;
    }

    public T Get  (clé de chaîne) où T: classe
    {
        return _cache.Get  (clé, ReadStrategy.Immediate);
    }

    public CacheEvictionPolicy GetDefaultPolicy ()
    {
        int minutes = 5;

        renvoie un nouveau CacheEvictionPolicy (nouveau TimeSpan (0, minutes, 0), CacheTimeoutType.Absolute, Enumerable.Empty  (), nouvelle liste  () {MASTER_KEY});
    }

    public void Insert (clé de chaîne, valeur d'objet)
    {
        var cachePolicy = GetDefaultPolicy ();

        Insert (clé, valeur, cachePolicy);
    }

    public void Clear (clé de chaîne)
    {
        _cache.Remove (clé);
    }

    public void ClearAll ()
    {
        _cache.Remove (MASTER_KEY);
    }
} 

La ​​chose importante à noter ici est que GetDefaultPolicy () est actuellement codé en dur pour mettre en cache les résultats pendant 5 minutes maximum. Il s'agit d'un paramètre que vous pouvez exposer dans le CMS ou pousser vers un fichier de configuration. Vous voudrez peut-être que ce soit excessivement petit (par exemple 5 minutes ou moins), ou augmenté pour être très prudent, par exemple 2 heures ou plus. L'autre chose à noter est que je lie cette politique de mise en cache à toutes les insertions et que tous les objets mis en cache sont liés à la même clé principale. N'hésitez pas à l'échanger comme bon vous semble. Vous pouvez également appeler les opérations Clear () ou ClearAll () sur des actions spécifiques, telles qu'une publication de contenu, ou comme outil manuel pour les administrateurs de site lors du débogage de problèmes.

C'est une stratégie commune que j'ai utilisée sur tous les projets au cours des dernières années, que la plate-forme soit Episerver ou non. Je trouve cela très efficace, et mettre en place la bonne stratégie vous prépare vraiment à être beaucoup plus rapide lorsqu'il s'agit de mettre en œuvre des solutions Web modernes.

Enjoy!

À propos de l'auteur <! -: dmccurry, Architecte de solutions ->

Je suis un développeur Sitecore certifié, un singe de code et un nerd général. J'ai sauté dans l'espace .NET il y a 10 ans pour travailler sur des applications de classe entreprise et je n'ai jamais regardé en arrière. J'adore créer des choses, des Legos aux logiciels qui résolvent de vrais problèmes. Ai-je mentionné que j'aime les jeux vidéo?

Plus de cet auteur






Source link