DEV Community

Cover image for Le cache dans les applications web : le secret des performances
TechniveK
TechniveK

Posted on

Le cache dans les applications web : le secret des performances

Aujourd’hui, les utilisateurs n’ont pas de temps à perdre. Ils veulent des pages qui se chargent en un clin d'œil, une navigation rapide, et des performances de haut vol. Pour arriver à ce niveau de fluidité, les développeurs disposent d’une arme puissante : le cache.

Le terme "cache" est omniprésent dans les discussions sur la performance web. Le but, bien sûr, n'est pas d'appliquer du cache partout comme un sauvage ! Non, il faut comprendre quand, pourquoi et surtout comment implémenter le bon cache au bon endroit. Il en existe plein de types différents : cache navigateur, cache serveur, cache d’API et même cache en base de données, chacun jouant un rôle particulier.
Dans cet article, je te propose de passer en revue tout ça, pour que tu puisses faire de ton application un petit bolide ! 🚨 🚘


Le cache : essentiel pour plusieurs raisons

  • Amélioration des performances : en stockant des résultats souvent demandés, le cache permet d'éviter de répéter des calculs coûteux ou de recharger des données à chaque requête.
  • Réduction de la charge du serveur : en limitant les appels à la base de données ou aux services tiers, tu réduis la charge globale du serveur.
  • Meilleure expérience utilisateur : un site rapide améliore l’expérience des utilisateurs et les encourage à rester plus longtemps.

1. Le cache navigateur : garder les ressources localement

Commençons par le plus familier : le cache navigateur. Comme son nom l’indique, c’est le navigateur de l’utilisateur qui gère ce type de cache. C’est un mécanisme côté client qui stocke les ressources localement sur l'appareil de l'utilisateur. Lorsque quelqu'un visite ton site, son navigateur télécharge les ressources nécessaires (HTML, CSS, JavaScript, images, polices de caractères, etc.) et les garde en cache pour une durée déterminée. Si l'utilisateur revient plus tard sur cette page, le navigateur ne redemande pas ces fichiers au serveur : il les charge directement depuis le cache local.

Comment ça fonctionne ?

Lorsque tu fais une requête HTTP, le serveur peut ajouter des en-têtes HTTP (headers) qui indiquent au navigateur comment et combien de temps il doit conserver les ressources en cache.

Les headers principaux sont :

  • Cache-Control : il indique au navigateur pendant combien de temps conserver un fichier (ex. Cache-Control: max-age=86400 pour 24h).
  • ETag : une sorte d'empreinte numérique (hash) du contenu. Si le contenu ne change pas, l'ETag reste le même et le navigateur sait qu’il peut réutiliser la ressource.
  • Last-Modified : le navigateur compare la date de la dernière modification pour savoir s'il doit recharger une ressource.

Exemple avec Symfony : configuration des en-têtes de cache

Dans Symfony, tu peux facilement contrôler le cache navigateur au niveau des réponses HTTP. Voici comment ajouter des directives de cache dans un contrôleur :

Headers HTTP browser cache

Le navigateur se fie aux en-têtes HTTP envoyés par ton serveur pour savoir combien de temps il peut garder une ressource en cache avant de la retélécharger. En gros, ces en-têtes disent au navigateur : "Tu peux conserver ces fichiers pendant X temps", ou bien "Vérifie auprès du serveur si ce fichier a changé avant de l'utiliser".

Exemple concret : une page de FAQ statique

Imagine que tu gères une page de FAQ qui ne change pas souvent. Avec un cache navigateur, tu peux demander au navigateur de garder la page en mémoire pendant une journée, sans jamais revenir vers le serveur.

En ajustant les directives max-age et immutable, tu peux t’assurer que cette page ne sera téléchargée qu’une seule fois par jour.

Headers HTTP complementary browser cache

Les avantages :

  • Rapidité pour l’utilisateur : il ne télécharge pas les fichiers à chaque visite.
  • Réduction des coûts serveurs : moins de requêtes signifie moins de charge.

Les limites :

  • Ça reste côté client : ce type de cache n'est accessible qu'à partir de l’appareil de l’utilisateur. Ce qui signifie que chaque nouvel utilisateur, ou chaque nouveau navigateur, doit d'abord télécharger les ressources avant que le cache ne soit utilisé.
  • Le cache navigateur ne peut rien faire pour accélérer la toute première visite d’un utilisateur.
  • Tu dois bien gérer les versions des fichiers pour ne pas que le cache garde des ressources obsolètes.

2. Le cache HTTP : l’optimisation côté serveur

Passons maintenant au cache HTTP. Là où le cache navigateur est une optimisation côté client, le cache HTTP se situe côté serveur.
Il est géré par des outils comme Varnish et il fonctionne comme un proxy qui s’interpose entre ton application web et l’utilisateur. Il peut servir des milliers de requêtes par seconde sans avoir à interroger PHP ou la base de données.

Comment ça marche ?

Varnish intercepte toutes les requêtes HTTP qui arrivent sur ton serveur et vérifie si une version de la page demandée est déjà disponible en cache. Si c'est le cas, il répond directement avec la page mise en cache, sans avoir à solliciter le serveur web ou la base de données. L’idée, c’est de stocker les réponses les plus fréquemment demandées pour éviter que ton application ne doive les générer à chaque fois. Résultat : des réponses ultra-rapides et un soulagement pour ton serveur.

Exemple de configuration Symfony pour Varnish :

Symfony te permet de contrôler facilement quels éléments doivent être mis en cache par Varnish grâce aux mêmes en-têtes HTTP que pour le cache navigateur.

Headers HTTP cache Varnish

Exemple concret : une liste d'articles de blog

Les articles de blog changent rarement une fois publiés. Tu peux donc utiliser un ETag pour permettre au cache HTTP de vérifier si le contenu a changé, sans que le navigateur ait besoin de télécharger à nouveau toute la page.

Lorsque l’utilisateur consulte la page, l’ETag généré à partir du contenu est comparé à celui que le cache a déjà stocké. Si rien n’a changé, la réponse 304 Not Modified est renvoyée, sans transférer le contenu à nouveau.

Les avantages du cache Varnish :

  • Optimisation pour tous les utilisateurs : contrairement au cache navigateur, Varnish agit pour tous les utilisateurs, même ceux qui visitent ton site pour la première fois.
  • Soulage le serveur : en servant directement des réponses en cache, Varnish évite de solliciter ton application ou ta base de données, ce qui améliore considérablement les performances sous charge.

3. Le cache système : optimiser les données à long terme

Le cache système intervient au niveau serveur et permet de stocker les résultats des calculs complexes, des requêtes lourdes en base de données, ou des réponses provenant de services tiers (API).

Dans Symfony, la manière la plus courante d’utiliser ce cache, c’est via le composant Cache qui te donne accès à une abstraction de plusieurs systèmes de cache (comme Redis, Memcached ou le file system).

Symfony propose une interface simple et efficace avec la fonction get(). Cette méthode permet d’accéder au cache si la clé existe déjà, ou de la créer si elle n’existe pas encore, tout cela en une seule ligne de code.

Exemple avec le FilesystemAdapter (cache sur disque)

Le FilesystemAdapter est une implémentation qui stocke les données en cache directement sur le disque de ton serveur. C’est pratique quand tu veux démarrer rapidement sans avoir besoin d'une solution de cache externe comme Redis.

Filesystem cache

Symfony te permet de gérer plusieurs types de cache via différents adaptateurs. Tu n’es donc pas limité au filesystem. Si tu veux passer à un cache en mémoire ultra-rapide, tu peux utiliser des services comme Redis ou Memcached.

Exemple avec RedisAdapter (cache en mémoire)

Cache Redis Symfony

Redis est un excellent choix pour les applications qui ont besoin d'un cache performant. Avec Redis, tu stockes les données directement en mémoire, ce qui est beaucoup plus rapide que le disque dur.

Avantages :

  • Moins de requêtes externes : tu diminues la charge sur les serveurs API.
  • Meilleures performances : tes utilisateurs reçoivent des réponses plus rapidement.

4. Le cache en base de données : optimiser les requêtes

On ne peut pas parler de cache sans mentionner le cache en base de données. Dans Symfony, tu peux éviter de refaire constamment les mêmes requêtes SQL coûteuses en utilisant des systèmes comme Doctrine Cache ou Redis.

Comment ça fonctionne ?

L’idée est de stocker les résultats de requêtes fréquemment demandées en mémoire. Quand la même requête est effectuée à nouveau, plutôt que de l’envoyer à la base de données, Symfony renvoie la réponse depuis le cache.

Exemple : Cache des produits les plus vendus

Imaginons que tu veuilles afficher la liste des produits les plus vendus dans une boutique e-commerce, une requête qui peut être lourde à exécuter.

SQL query cache

Autre méthode : utilisation du cache intégré à Doctrine (Result Cache)

Doctrine offre aussi son propre système de cache des résultats des requêtes. C’est particulièrement pratique pour cacher directement au niveau de l'ORM, en rendant le processus de mise en cache encore plus transparent.

Pour activer le Result Cache dans Doctrine, tu dois d’abord configurer un adaptateur de cache (comme Redis ou le système de fichiers) dans ton fichier doctrine.yaml :

doctrine.yaml

Ensuite, tu peux mettre en cache le résultat d’une requête directement dans ton repository.

Exemple : caching avec Doctrine Result Cache

Result Cache Doctrine

  1. useResultCache(true, 3600, 'top_selling_products') : On active le cache pour la requête avec une durée d’expiration d'une heure. La clé du cache est top_selling_products.
  2. Cache Redis via Doctrine : Doctrine enverra les résultats dans Redis (ou tout autre cache configuré), ce qui évite d'exécuter la même requête SQL plusieurs fois durant la période de cache.

Avantages :

  • Réduction de la charge sur la base de données : En mettant en cache les résultats, tu réduis considérablement la charge sur la base de données, surtout pour les requêtes lourdes ou fréquentes.
  • Amélioration des temps de réponse : En servant des résultats directement depuis le cache (qui peut être en mémoire avec Redis), tu réduis les temps d'accès par rapport à des requêtes SQL régulières.
  • Simplicité d’utilisation : Avec Symfony et Doctrine, la gestion du cache est rendue très facile grâce à des méthodes comme get() du composant Cache ou le Result Cache intégré à Doctrine.

Maintenant que tu maîtrises chaque type de cache, la question qui brûle les lèvres : comment tout ça fonctionne ensemble ?

En fait, c'est la complémentarité des caches qui te permet d’avoir une application vraiment performante. Le cache navigateur accélère les visites répétées d'un utilisateur en stockant les ressources directement sur son appareil. Le cache HTTP (Varnish), lui, optimise la charge côté serveur en servant les pages générées directement depuis sa mémoire.

L’objectif ? Gagner sur tous les tableaux. Le navigateur fait en sorte que l'utilisateur ne retélécharge pas inutilement des fichiers. Varnish, de son côté, fait en sorte que ton serveur ne soit pas surchargé par des requêtes redondantes.

Conclusion

Que ce soit côté client ou côté serveur, tout est une question de bon équilibre. Chaque type de cache a ses avantages et ses inconvénients, mais en les combinant judicieusement, tu peux atteindre des performances spectaculaires.

Alors, prends le temps de bien configurer tes caches, car ils peuvent faire toute la différence entre une application lente et une application rapide comme l’éclair !

Top comments (2)

Collapse
 
greenersoft profile image
GreenerSoft

Très bon article qui fait bien le tour de la question.

Collapse
 
technivek profile image
TechniveK

Merci beaucoup @greenersoft !