La gestion du cache en général n’a jamais été un problème simple à résoudre. Drupal ne propose pas non plus de solution « miracle » , mais prend en charge le cache de plus en plus finement, et donc efficacement. Notons que l'on ne parlera pas ici des systèmes externes à Drupal, comme par exemple Varnish, Redis..., même s'ils ont un intérêt évident. Découvrons donc le fonctionnement du cache de rendu de Drupal 8.

Commençons par LA règle d’or de la gestion du cache :

" Il n’existe pas de règle d’or. "

La gestion du cache dépend très largement du site lui-même, de ses fonctionnalités et de la réactivité souhaitée mais également du trafic attendu. Par exemple un blog sur la pêche à la mouche en Ardèche ne nécessite pas forcément de mettre fortement en cache chaque page puisque le trafic du site est sans doute faible et réparti sur la journée. Au contraire un site de vente en ligne qui lance des promotions à une date/heure précise doit offrir à la fois une très bonne réactivité et des données en temps réelles (par exemple pour la gestion du stock). Une bonne gestion du cache est alors indispensable voire cruciale.

Il est nécessaire d’avoir une stratégie de cache adaptée à chaque site, en fonction de la fréquence des mises en lignes et du trafic, principalement.

C’est quoi mettre en cache ?

De façon basique on met en cache car on a effectué une tâche plus ou moins lourde et on ne souhaite pas la réitérer puisque son résultat est le même. Oui, mais la question est : pendant combien de temps son résultat est identique ? Comment le savoir sans relancer cette tâche ? On est au coeur du sujet que Drupal 8 adresse avec sa gestion du cache de rendu (cache API).

La production du code HTML est très gourmande et nécessite donc une mise en cache très fine. Il faut éviter de re-générer un rendu qui n'a pas changé et en même temps s'assurer que les données affichées sont bien à jour.

On peut partir de 2 constats :

  • Plus un site a de trafic, plus il est nécessaire de mettre en cache.

  • Plus l’affichage est dynamique, plus la gestion du cache est complexe.

Ici on s'attache au cache de rendu, mais ce n'est pas le seul cache que gère Drupal 8. Il existe d'autres caches, comme le cache des entités, le cache des plugins... Ce sont tous les caches que l'on vide en utilisant Drush (commande drush cr).

Gestion du cache avec Drupal

Une page est constituée de multiples fragments HTML (render arrays), comme par exemple le bloc contenant le titre, le logo et le slogan du site. Certains de ces fragments sont statiques tandis que d’autres sont dynamiques (parfois très fortement). Drupal est capable de mettre en cache chaque fragment individuellement (service renderer). Tous ces fragments sont stockés en base, ce qui signifie que récupérer ces informations en cache nécessite de nombreuses requêtes ! Malheureusement l’accès à une base de données n’est pas très performant.

Pour diminuer le temps d’assemblage d’une page, Drupal est capable de mettre en cache une page complète d’un point de vue HTML à partir des fragments statiques et en ajoutant des placeholders pour les fragments dynamiques (module Internal Dynamic Page Cache). Ainsi le code principal d’une page est stocké en base et ne nécessite qu’une requête pour le récupérer. Ceci n'est efficace que si l’on a principalement des parties de page statiques; les parties dynamiques doivent être recalculées plus régulièrement. Il est à noter que tous les utilisateurs, même anonymes, bénéficient de cette mise en cache.

Afin d'améliorer encore la vitesse de rendu d'une page, les anonymes profitent d'une mise en cache complète de chaque page. En effet par défaut les anonymes n'ayant pas de session, le contenu est identique pour tous ces utilisateurs. C'est le rôle du module Internal Page Cache. On est capable alors de stocker 100% du code HTML de chaque page en base de donnée.

Enfin le module BigPipe améliore encore les performances perçues. Il permet d'envoyer une page au client, même si cette dernière est incomplète (placeholder vide). Ainsi le navigateur est capable d'afficher une page sans tout son contenu, et les parties HTML manquantes sont streamées dès que le serveur les a calculées.

Qui doit s’occuper de la gestion du cache ?

En ce qui concerne le cache de rendu de Drupal, il en va de la responsabilité des développeurs. Tout ce qui concerne un affichage (route et/ou bloc) il est indispensable d’indiquer quelle mise en cache on souhaite. On peut pour se faire jouer sur 3 paramètres : 

  • Les contextes : variations de l’affichage.

  • Les tags : dépendance à des objets de Drupal (entités de contenus et/ou de configuration).

  • Le temps : durée de mise en cache.

Notons que par défaut Drupal 8 met en cache en ajoutant 3 contextes : le thème, les permissions de l’utilisateur et la langue. Ceci est cependant paramétrable via le fichier de services/paramètres de services /web/sites/default/services.yml.

Comment peut-on utiliser ces informations de cache ?

Lorsque l’on affiche des données, il faut se poser la question de savoir si ce que l’on affiche peut avoir des variations. Par exemple si j’affiche le nom de l’utilisateur courant, l’affichage a autant de variations qu’il y a d’utilisateurs différents du site.

De la même façon, si un des utilisateurs modifie son nom, alors notre affichage doit être invalidé et recalculé lors du prochain affichage. Il faut donc ajouter une dépendance vers les comptes utilisateurs.

Le temps de mise en cache est arbitraire et peut avoir une grande influence sur les performances globales du site. Par exemple pour un site ayant des milliers de connexions simultanées, il peut être très efficace d’utiliser un temps de mise en cache de quelques secondes. Le site est globalement bien à jour et le serveur est soulagé d’une partie de la charge.

Notons que les clés de cache indique à Drupal que l’on souhaite enregistrer en base l’affichage. Si aucune clé n’est renseignée, alors les informations de cache sont attribuées au parent.

Afin de bien mettre en place le cache d’un site, il est nécessaire de faire de très nombreux tests d’affichage afin de s’assurer que les bonnes informations sont affichées aux bons utilisateurs et qu’elles sont à jour. Cela nécessite donc de tester avec des utilisateurs ayant des rôles différents mais également avec des utilisateurs ayants les mêmes rôles. Ceci est chronophage mais indispensable !

Attention à ne pas mettre trop en cache; certaines données que l’on affiche peuvent varier très fréquemment, ce qui impliquent que le cache correspondant est invalidé continuellement. Il peut donc être plus efficace de ne pas mettre en cache et de calculer leur affichage à la volée. Mais encore une fois, il n’y a pas de technique qui marche à chaque fois.

Si vous estimez qu'une mise en cache n'est pas nécessaire pour certains affichages, par exemple dans le cas où les données affichées doivent être toujours à jour, vous pouvez simplement indiquer un max-age de 0, sans définir de clé de cache. Cela indique à Drupal de ne pas mettre en cache en base et d'ajouter un placeholder automatiquement. Ainsi le contenu sera compatible avec le module BigPipe et ne retardera pas l'affichage de la page. Notons que les conditions d'auto-placeholdering (par exemple max-age => 0) sont définies dans le fichier web/sites/default/services.yml.

Génération de pages statiques - le grand retour en arrière !

Étant donné la complexité d’avoir un site performant et toujours à jour, il est également possible de générer un site statique : chaque page est un fichier HTML statique et le serveur invalide cette dernière quand cela est nécessaire. Attention cela réduit beaucoup les interactions avec les utilisateurs. On se rapproche du Web 1.0 !

L'idée est que le serveur n'ait qu'à envoyer des fichiers statiques (HTML, CSS, JS, images...) sans avoir quoi que ce soit à calculer. Ainsi les performances sont maximales. Cela ne résout pas non plus tous les problèmes, et en particulier cela ne dispense pas d'avoir à invalider certaines pages quand leurs contenus changent. D'autre part cela n'est envisageable que si les utilisateurs sont anonymes ou bien que le contenu des pages ne dépends pas des utilisateurs. D'autre part il faudra aussi gérer les formulaires (accès à la base de données, tokens, captcha...). Ainsi la génération statique d'un site Drupal n'est pas non plus la solution idéale dans tous les cas !

Conclusion

La gestion du cache est compliquée et nécessite de bien comprendre ce que l'on fait. De nombreux sites faits avec Drupal 8 ont des problèmes de performance dûs à une mauvaise utilisation de la Cache API. Au delà de la mise en cache native de Drupal, il ne faut pas oublier tout ce qui est autour : optimisations de la base de données, du serveur, des assets, des images, etc... La performance des sites web est un sujet très vaste et de plus en plus complexe. Il n'en reste pas moins de plus en plus indispensable.

Ressources :

 

Dans la même catégorie

CMS Drupal

Drupal : LE CMS pour les professionnels ?


Drupal et les structures de données

Que reste-t-il à Drupal ?


Drupal et les structures de données

Drupal et les structures de données