Facebook EmaiInACirclel
Développement front-end, back-end

Cache sur les projets web

Constantin Samoila
Constantin Samoila
Expert Cloud et Infogérance

Le cache sur les projets web

L’offre applicative actuelle, qu’elle soit dans les SI internes ou dans les services offerts aux internautes, repose sur une attente élevée de performances de la part des utilisateurs. Ces derniers voulaient des sites Web performants, les ont obtenus et ils expriment dorénavant les mêmes attentes de la part de leurs applications professionnelles en ligne.
Dans cet article nous traiterons de l’un des principaux concepts clé de la performance des applications web: le Cache qui opère en maximisant la réutilisation des ressources. En plus de traiter les différents types de cache qui agissent à chaque niveau de l’architecture applicative, nous allons voir aussi un exemple pratique de cache de présentation, celui du framework Microsoft Asp.net MVC 4

La performance des applications web

Le sujet de la performance des sites web reste vaste  et ce domaine n’a pas la maturité d’autres domaines transversaux apparentés (architecture ou stockage des données). La question essentielle qui se pose lorsqu’on parle de performance est quand faut-il s’en préoccuper ?

Si cela se fait au plus tôt du point de vue du concepteur d’applications agiles, l’approche est problématique : nous risquons d’optimiser des choses inutiles et nous pouvons masquer de gros problèmes de l’application.
Le remettre à plus tard comporte aussi des risques car les coûts de réalisation des changements nécessaires peuvent être énormes.

Nous recommanderons plutôt une voie médiane : concevoir l’architecture, les structures de persistance et les algorithmes en suivant une approche de design pour la performance et ne traiter les problèmes de performance qu’au moment de passer à l’échelle. Là encore ne traiter que les « zones chaudes » qui auront été détectées au cours des itérations de développement. Cette approche sera évoquée dans de futurs articles car il y a beaucoup à dire et à partager sur ce sujet. Ici, nous nous concentrerons sur une technique de traitement a posteriori des « zones chaudes » d’une application.
Pour quoi se focaliser sur le cache dans cet article ? Il s’agit de notre conviction d’auteur que le cache est l’outil dont l’utilité marginale est la plus forte dès qu’il s’agit de maximiser les performances d’une application web. Du reste, il s’agit de l’une des techniques les plus faciles à mettre en œuvre.

Le cache ou plus exactement la mémoire-cache est un système qui stocke temporairement des résultats de requêtes et les retransmet au besoin de façon transparente afin d’accélérer les requêtes. Et par requête, nous entendons toute demande d’un client qui requiert une réponse d’un serveur.

Les systèmes de cache ont un grand avantage lorsque les améliorations de performances sont effectuées une fois que le code applicatif est écrit : ce sont souvent des solutions automatiques, transversales au projet et hautement configurables qui ne nécessitent aucun changement de code. Chaque changement sur le code d’un projet impliquant des coûts importants, on mesure aisément l’avantage de telles solutions.

Types de cache pour les projets web

Voici des types de cache que nous pouvons utiliser :


Cache projets web

Couche Type de cache Description
Base de données Cache des requêtes La base de données utilise un cache propre pour optimiser la performance. Une application exécute beaucoup de requêtes dont seulement une portion est unique. La base de données anticipe cela et garde dans le cache les données les plus utilisées et le résultat de certaines requêtes.
Application Cache local d’accès aux données Les appels vers la base de données sont coûteux,  ce qui fait qu’un cache local est toujours utile. Cela peut être fait manuellement ou plus souvent, dans les cas des ORM, au moyen d’un framework spécialisé. La performance est améliorée par l’optimisation de la communication avec la base de données. Ce système peut utiliser plusieurs niveaux de cache; chaque niveau apporte un certain équilibre entre la vitesse et l’espace de stockage.
Cache des objets métiers Le cœur d’un projet est représenté par les objets métiers et leurs interactions. Un cache sur les objets métiers augmente la performance car nous sommes sur un autre niveau que la base de données et ici  un objet peut être créé en utilisant des dizaines de requêtes. En ce qui concerne l’implémentation finale le cache pour ces éléments peut être gardé dans la mémoire mais pour des grandes applications l’utilisation d’un cache distribué (comme memcache) est recommandée.
Cache de présentation La couche de présentation fait le lien entre les objets métiers et leur représentation graphique sur le terminal de l’utilisateur (typiquement un navigateur Internet) en traduisant ces objets dans un format final (HTML, JSON, XML, etc), en utilisant souvent des objets intermédiaires. Ces représentations intermédiaires peuvent être stockées en cache.
Réseaux Cache serveur proxy Avec ce type de cache nous augmentons la performance en plaçant dans le cache une partie du trafic entre le serveur et l’utilisateur final. C’est un système de cache passif car l’application web ne participe pas d’une manière directe.
Réseau de distribution du contenu – CDN Ce système de cache implique l’utilisation d’un serveur très rapide qui peut accueillir toutes sortes de ressources utilisés par le projet. Un clip vidéo peut être transmis plus rapidement par un CDN que par le projet web lui-même. La même logique peut être utilisée pour les ressources HTML, les fichiers CSS, JavaScript, les images, les flux vidéos, en un mot les structures de données statiques.
Navigateur Cache HTTP Le protocole HTTP supporte des fonctionnalités de contrôle du cache d’un navigateur. Les informations des en-têtes HTTP aident le navigateur à retransmettre une ressource a partir de son cache, ce qui fait qu’une requête vers le serveur est gagnée. Le cache du navigateur peut être augmenté par l’utilisation d’un CDN. Par exemple, le fichier du code de jQuery réside sur un CDN et beaucoup d’applications web l’utilisent. Le navigateur va lire une première fois ce fichier et le garder dans son propre cache en cas de visite du même site ou d’un autre site qui utilise la même version de jQuery.

Exemple pratique pour un cache

Pour démontrer le pouvoir du cache nous allons réaliser des tests de mesure de performances sur un projet web Asp.net MVC.

Contexte

Pour tester les différents types de cache et pour avoir des valeurs qui sont le plus proche possible de la réalité nous mettons en place une application web réaliste. Nous souhaitons que l’application reprenne une requête web moyenne. En terme d’exigences, notre environnement de test répondra à ces spécifications.

Demandes de l’application Implémentation
Une base de données de complexité et de volume moyens Nous utiliserons une base de données exemple de Microsoft: Northwind. Pour le volume nous mettons 5000 lignes dans chaque table utilisée : produit, ordre fournisseur, etc
L’utilisation d’un ORM et des valeurs moyennes pour le nombre de requêtes SQL exécutées et pour le volume extrait de la base Nous utilisons Entity Framework 5.0. L’application réalise autour de 50 requêtes SQL pour construire une page pour l’utilisateur. Chaque requête retourne un résultat de 20 à 30 enregistrements. Nous simulons aussi l’utilisation de la pagination
Volume moyen du code HTML produit par Asp.net MVC Nous produisons 25 KB de HTML dans les vues de Asp.net MVC
Conditions moyennes de déploiement L’application est hébergée sur 2 serveurs Windows 2008 x64, l’un pour le serveur HTTP et l’autre pour la base de données

Qu’est ce qu’on mesure ?

Nous nous intéresserons à l’impact des différents types de cache sur la performance du projet autour d’une seule requête web. Nous allons donc mesurer la durée de service de cette requête et obtenir un indicateur sur le nombre de requêtes transmises par seconde (débit de performance, throughput en anglais). Pour obtenir des valeurs représentatives nous faisons 100 requêtes l’une après l’autre et nous gardons la valeur moyenne du temps de réponse afin de lisser l’effet de dispersion dû aux instabilités du réseau. Pour réaliser les tests nous utilisons l’outil « ab » de la suite Apache Serveur HTTP.

Performance standard

Tout d’abord, nous mesurons la performance standard, c’est-à-dire le débit de performance de l’application sans mettre en place un type de cache en particulier. Nous prenons 5 mesures sur 100 sur un temps de test de 25 minutes. Cette performance standard s’établit à 2.75 requêtes/seconde ce qui est très faible et totalement en deçà des performances attendues par l’utilisateur le moins exigeant.

Mémoire-cache d’objets métier
Le premier type de cache que nous mettons en œuvre est le cache des objets métiers. Dans des conditions réelles, aucun objet métier ne peut résider dans le cache pendant très longtemps car l’objet métier étant dynamique et transactionnel, sa représentation en cache sera invalidée dès que l’état de l’objet aura changé. Pour produire des valeurs réalistes qui tiennent compte des invalidations, nous réalisons 3 types de tests ici, en fonction du pourcentage des opérations du cœur métier qui sont mises en cache : 100%, 75% et 50%.

Pourcentage des opérations cachées Requêtes/seconde
100% 111
75% 103
50% 86

Nous obtenons un débit de performance de 100 requêtes/seconde en moyenne. L’amélioration de la performance par rapport au cas de performance standard est appréciable : une croissance de plus de 3500% ! Cette amélioration n’a eu aucun impact direct dans le code car la mise en œuvre n’a requis que peu de configuration du conteneur d’injection de dépendance qui supporte une mémoire-cache pour chaque objet qu’il injecte.
La dégradation du débit de performance en fonction de la proportion d’objets en cache n’est pas linéaire, c’est encore une bonne raison pour utiliser cette technologie car même en présence d’un fort taux d’invalidation, la fraction des objets métier qui résidera encore dans le cache conduira à des performances améliorées. Parmi les raisons qui expliquent ce comportement, on peut citer le fait que les différentes opérations du cœur métier ne sont pas identiques en termes de consommation de ressources. La différence observée entre 100% et 50% est plus faible car nous avons choisi de toujours mettre en cache les opérations les plus coûteuses.

Cache d’objets métier distribué

L’une des limitations du système précédent est que la mémoire n’est pas partagée par les serveurs dans une ferme web. Dans ce type de configuration, notre système produit des résultats au niveau d’un serveur et ces résultats ne sont pas partagés sur les autres serveurs. Une solution est de mettre en œuvre un système de cache distribués, comme memcache. Le cache ne reste plus dans la mémoire mais dans une couche externe, non transactionnelle et tolérante aux ruptures du réseau. Pour notre test nous avons employé Couchebase (une implémentation JSON de memcache). Là encore, aucune modification du code applicatif n’est requise. Le framework d’injection supporte nativement le protocole de memcache.

Nous avons opté pour une configuration de 50% d’objets métiers placés en cache pour tenir compte du plus haut taux d’invalidation induit par le partage du cache entre plusieurs serveurs d’application.
Le débit de performance s’établit en moyenne à 18,3 requêtes/seconde. L’amélioration est moindre que dans le cas du cache dédié mais, dans ce cas précis, nous payons le prix de la communication réseau et de la sérialisation en JSON des objets.

Cache de présentation ASP.NET MVC

Dans ce dernier cas de test, nous utiliserons le cache standard du framework MVC de ASP.NET : le résultat complet d’une requête web est mis en cache pour une certaine période. Ce type de cache est très performant car il tire parti de son intégration avec le framework pour éviter certaines opérations coûteuses (action dans le contrôleur, recherche et exécution des vues et des vues partielles).

Les mesures indiquent un débit de performance moyen de 275 requêtes/seconde. Cette valeur est la meilleure de tous les environnements testés et s’explique par le fait que les invalidations des données manipulées dans la couche de présentation ont moins d’impact quant à leur réutilisation depuis le cache.

Ce type de cache a le plus grand impact sur la performance d’un projet moyen et est aussi facile à mettre en place et à configurer. Son seul défaut est de nécessiter une technologie hôte bien particulière (ici le framework MVC de ASP.NET). Il conviendra, pour l’architecte de solutions logicielles, donc de choisir une technologie de mise en œuvre de la couche de présentation de l’application qui propose une technologie de mémoire-cache efficace et pratique.

Cet article a été rédigé par Irinel Matei, ex expert .Net Pentalog


2 Commentaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *