Manuel:Cache des fichiers

This page is a translated version of the page Manual:File cache and the translation is 100% complete.

MediaWiki possède un schéma simplifié optionnel pour enregistrer dans le cache, le HTML généré des pages d'articles. .

Opération et utilisation

Le cache des fichiers ne sert qu'aux utilisateurs anonymes qui affichent tous le même code HTML généré. Les utilisateurs connectés ne bénéficient pas de ce cache parce que leur page est personnalisée; elle contient leur nom, l'habillage qu'ils ont choisi, etc...

Le cache des fichiers est activé en initialisant les variables $wgUseFileCache et $wgFileCacheDirectory dans LocalSettings.php :

$wgUseFileCache = true; // par défaut : false
$wgFileCacheDirectory = "$IP/images/cache"; // par défaut : "{$wgUploadDirectory}/cache" vaut "$IP/images/cache"

Ceci a pour conséquence que la page web HTML générée pour chaque page du wiki, sera rangée dans un fichier dédié sur le disque dur. Toute les demandes ultérieures émanant d'utilisateurs anonymes sont répondues non pas en générant de nouveau la page mais simplement en renvoyant la version du fichier HTML qui a été enregistré sur le disque. Ceci permet d'optimiser le temps de réponse.

Le texte web HTML généré est mis sur le disque dans les répertoires sous $wgFileCacheDirectory et ressemble à ceci :

-rw-r--r-- 1 apache apache 57421 Jan  7 01:58 cache/0/04/P%C3%A1gina_principal.html
-rw-r--r-- 1 apache apache 29608 Jan  4 16:37 cache/1/17/P%C3%A1gina_Riscada.html
-rw-r--r-- 1 apache apache 21592 Jan  3 07:27 cache/1/1c/P%C3%A1gina_Duplicada.html
-rw-r--r-- 1 apache apache 36088 Jan  7 02:03 cache/2/24/P%C3%A1gina_principal_alternativa.html
-rw-r--r-- 1 apache apache 44205 Jan  7 06:10 cache/a/a4/P%C3%A1gina_linkada.html
-rw-r--r-- 1 apache apache 24686 Jan  3 07:27 cache/d/db/P%C3%A1gina_Invertida.html
-rw-r--r-- 1 apache apache 17222 Jan  3 06:28 cache/f/f0/P%C3%A1gina_n%C3%A3o_encontrada.html

Dans cet exemple, le répertoire du cache des fichiers est cache/ et les pages du wiki sont enregistrées dans chaque fichier Página... (P%C3%A1gina...), avec une correspondance d'un fichier Página_....html pour une page du wiki. Ces fichiers sont créés au fur et à mesure que les utilisateurs visitent les articles du wiki; vous pouvez tous les créer en une seule passe avec le script de maintenance rebuildFileCache.php .

Le cache des fichiers est assez rustique; il n'y a pas de durée limite de présence dans le cache pour les pages générées et elles sont mises en cache inconditionnellemnt, même si elles contiennent des variables, des extensions, et d'autres sorties variables. Certaines extensions suppriment la mise en cache pour les pages ayant un contenu dynamique.

Pour un résultat plus parlant, considerez l'utilisation de $wgUseGzip à la place de (ou combiné avec).

Pour des sites plus gros, l'utilisation d'un cache externe tel que Squid ou Varnish est préférable pour l'activation du cache des fichiers.

Si le cache des fichiers semble ne pas fonctionner, assurez-vous que le serveur web a la permission d'écrire dans le répertoire que vous avez choisi.

Limitations

Les noms de fichier des fichiers du cache sont définis en fonction du titre des pages. En fonction de la langue utilisée pour le titre des pages, certains caractères du nom de fichier devront être encodés pour obtenir un nom de fichier compatible avec le système de fichiers. Pour les langues telles que l'arabe, le chinois et autres, cela peut se traduire par l'avertissement PHP suivant :

PHP Warning:  file_put_contents(cache/......html.gz): failed to open stream: File name too long in includes/cache/FileCacheBase.php on line 171

Ceci est une limitation connue. Voir tâche T148684.

Les pages des catégories et les descriptions des images ne sont pas effacées du cache. Par exemple, l'ajout ou la supression d'une page dans une catégorie ne met pas à jour la page de catégorie, ce qui fait que les utilisateurs non connectés ne voient pas les modifications de cette dernière. Ceci est une limitation connue. Voir tâche T26575

Domaine et intervalle

L'utilisation du cache ne se fait que pour les utilisateurs qui :

  • ne sont pas connectés.
  • qui n'ont pas leur indicateur user_newtalk d'activé.

Les pages qui entrent dans le cache :

  • ne sont pas des pages spéciales.
  • ne sont pas des redirections.
  • sont affichées dans leur version actuelle, vue simple, sans paramètres d'URL

Ceci couvre la majorité des requêtes du wiki, mais il est encore important de configurer le bytecode et le cache des applications pour gérer tout le reste.

Validation

La date de modification du fichier en cache est comparée avec la date se trouvant dans la variable globale $wgCacheEpoch initialisée dans LocalSettings.php à chaque visualisation.

Si le fichier est au moins aussi récent que ces deux dates, il est considéré comme valide et envoyé directement au client. S'il est plus ancien, ou n'existe pas, l'analyse syntaxique de la page et sa génération continuent et les résultats sont sauvegardés pour une utilisation ultérieure.

Invalidation

Le cache entier peut être invalidé en initialisant $wgCacheEpoch à l'heure actuelle, ou en supprimant tous les fichiers du cache.

Les pages individuelles sont invalidées en initialisant leur champ page.page_touched par l'appel pratique de Title::invalidateCache(). Ceci doit être fait à la création de l'article, à l'enregistrement des modifications, au renommage, et à la création et la suppression des articles liés (pour mettre à jour les liens modifiés). Les opérations d'invalidation qui apparaissent lors de la modification des modèles par exemple, le contrôle des pages qui utilisent le modèle pour comparer la date en cache avec page_touched.

Certains cas ne sont pas encore bien gérés, ce qui inclut probablement :

  • le 'reload' ou 'refresh' du navigateur (ne recharge que la page en cache sans en faire la mise à jour)
  • les variables de sortie des extensions telles que Extension:DynamicPageList désactivent la mise en cache de ces pages afin d'éviter d'avoir des données périmées. Celles qui ne le font pas, retournent les données périmées même lors du rechargement de la page par le navigateur.
  • certain longs messages d'erreur peuvent être mis en cache indéfiniment comme s'ils étaient du contenu valide de page; seulement ?action=purge va les supprimer du cache après qu'il y auront été enregistrés. Un seuil de taille minimale des sorties est utilisé pour éviter la mise en cache de la plupart des errreurs, comme les erreurs PHP fatales.

Voir aussi : Manuel:$wgInvalidateCacheOnLocalSettingsChange .

Expiration

Des méthodes d'expiration des pages du cache doivent probablement exister, particulièrement pour les pages qui contiennent des variables (la date: nous sommes le XXXX, des valeurs: nous avons XXXX articles, ...).

Si $parserOutput->getCacheTime() vaut -1, la mise en cache des fichiers sera désactivée pour la sortie de la page. Aucune disposition ne permet de définir une date d'expiration. Par conséquent, l'ensemble du code HTML de toutes les pages est mis en cache pour toujours. Une commande explicite ?action=purge (ou une édition de la page) régénérera cette page, mais ni les indicateurs internes de non mise en cache de MediaWiki, ni le rechargement par le navigateur ne supprimeront les sorties d'extension obsolètes une fois qu'elles auront été stockées comme partie de page mise en fichier dans le cache.

Onglet de rafraichissement

Il est possible d'ajouter un onglet pour forcer une page individuelle à devenir non-valide et la rafraîchir, en utilisant ?action=purge et l'extension Purge page.

Compression

Optionnellement, le cache peut être compressé pour économiser de la place et de la largeur de bande. (Ceci nécessite que zlib soit activé dans le PHP config.)

$wgUseGzip = true;

Si la compression est activée, les fichiers en cache sont sauvegardés avec l'extension .html.gz. Les navigateurs qui annoncent la prise en charge de gzip dans leur champ Accept-Encoding recevront directement la version compressée; pour les navigateurs qui ne le font pas, nous décompressons les données à la volée et nous leur envoyons le texte en clair.

Un entête "Vary: User-agent" sera envoyé pour dire au cache du proxy de faire plus attention à qui il renvoie les données. (« Vary: Accept-encoding » serait plus approprié, mais Internet Explorer refuse de mettre en cache les pages marquées ainsi.)

  Avertissement : N'activez pas $wgUseGzip si vous utilisez la mise en tampon de vos sorties compressées (par ob_gzhandler ou zlib.output_compression). En faisant cela vous afficherez des pages incohérentes aux utilisateurs.

Repli d'urgence

Si le wiki ne peut pas contacter le serveur de base de données, il essaiera d'afficher la version mise en cache de la page demandée, qu'elle soit actuelle ou non, avec un message « database is down » ajouté.

Ceci possède quelques limitations :

  • les pages spéciales ne sont pas couvertes, en aucune manière, il y a juste un message d'avertissement
  • les pages de redirection ne sont pas mises en cache, donc un clic sur un lien de redirection ne mène pas à la destination finale.
  • les pages avec des deux-points dans le titre (autres que pour un espace de noms valide) peuvent toujours échouer car MediaWiki vérifie si le titre contient un préfixe interwiki valide. Cela se produit uniquement s'il n'y a pas d'entrée de cache interwiki pour le préfixe de la page (voir $wgInterwikiExpiry ) ou si $wgMainCacheType se replie sur (ou est défini à) DB_CACHE.
  • les tentatives d'utilisation d'actions sans affichage entraînent une page simple, ce qui peut prêter à confusion
  • il peut y avoir des problèmes avec le délai de connexion MySQL, qui la rendent longue à s'établir avant d'échouer, en particulier si vous utilisez des connexions persistantes et que la base de données s'arrête ensuite. Ajustez mysql.connect_timeout (défini à 3 ou plus) dans php.ini pour gérer ce problème. Modifiez le php.ini du serveur web et non le php.ini du client.
  • le repli peut échouer si $wgStatsMethod vaut cache et $wgMainCacheType se replie (ou est initialisé à) DB_CACHE


Répondre directement avec les pages du cache

Par défaut, MediaWiki transmet la page de cache avec PHP. Voici comment nous utilisons les astuces de configuration du serveur web pour servir directement les fichiers en cache sans invoquer MediaWiki ou PHP du tout.

D'abord, définissez $wgFileCacheDepth = 0;. Ensuite, nous ajoutons des règles de réécriture. Voir ci-dessous.

Apache

La règle mod_rewrite suivante fonctionne dans le fichier .htaccess sur un hôte web partagé exécutant Apache 2.2 :

RewriteBase /
# If a cached page exists under /w/html_cache, do an internal redirect to it:
RewriteCond %{HTTP_COOKIE} !UserID=
RewriteCond %{QUERY_STRING} !.
RewriteCond %{DOCUMENT_ROOT}/w/html_cache/$1.html -s
RewriteRule ^wiki/(.+)$ /w/html_cache/$1.html [B,L,NS]

Toutefois, cette règle de réécriture ne fonctionnera pas correctement pour les pages dont les titres contiennent des signes de ponctuation ou des caractères non-ASCII. Une solution judicieuse consisterait à utiliser une correspondance de réécriture (RewriteMap), mais cela n’est pas pris en charge dans le contexte .htaccess. Au lieu de cela, l'astuce suivante peut être utilisée pour gérer les titres non-ASCII en extrayant le titre échappé de l'URL directement à partir de la ligne de demande brute :

RewriteBase /
# If a cached page exists under /w/html_cache, do an internal redirect to it: 
RewriteCond %{HTTP_COOKIE} !UserID=
RewriteCond %{QUERY_STRING} !.
ReWriteCond %{THE_REQUEST} ^GET\x20/wiki/([^\x20/]+)\x20HTTP
RewriteCond %{DOCUMENT_ROOT}/w/html_cache/%1.html -s
RewriteRule ^wiki/(.+)$ /w/html_cache/%1.html [B,L,NS]

The previous rewrite rules will handle requests of the form

https://site/wiki/Page_Name

To handle requests where the Page_Name is in the QUERY_STRING like

https://site/w/index.php?title=Page_Name

the following works:

RewriteCond %{HTTP_COOKIE} !UserID=
RewriteCond %{QUERY_STRING} ^title=([^&]+)$
RewriteCond %{DOCUMENT_ROOT}/images/cache/ns0\%3A%1.html -s
RewriteRule ^ /images/cache/ns0\%253A%1.html? [B,L,NS]

Cela ne correspondra toujours pas aux titres contenant des points, des barres obliques ou d’autres signes de ponctuation que le cache de fichiers échappe, mais pas les navigateurs (ou vice versa). Il faut aussi s'assurer que l'entête Vary ad'hoc a été envoyée  :

Header append Vary Cookie

Notez aussi que, comme cette astuce de redirection contourne complètement MediaWiki, elle ne respectera pas $wgCacheEpoch . Il est possible à la place, que vous deviez effacer ou reconstruire le cache manuellement si besoin.

Nginx

Comme le langage de configuration de nginx est assez limité (il ne permet pas les instructions imbriquées if par exemple), il nécessite le module ngx_lua.

La configuration suivante doit être intégrée dans votre bloc serveur et suppose que :

  • vous utilisez des URL fantaisistes comme example.com/Page;
  • votre dossier de cache est à l'intérieur de votre dossier MediaWiki (par défaut);
  • vous envoyez déjà les fichiers *.php par proxy à php-fpm (ou autre) dans le dernier bloc d'emplacement.

Et voici les limitations :

  • comme avec la solution Apache, vous devez exécuter une tâche cron ou reconstruire les fichiers du cache manuellement lorsqu'ils sont modifiés;
  • les pages dont le titre contient des caractères non-ASCII sont servies via PHP (ce qui devrait être transparent pour l'utilisateur de toute façon).

Modifier les chemins si nécessaire.

 location ~ /cache/(.*) {
     internal;
 }
 
 location / {
     default_type 'text/html';
     rewrite_by_lua '
         local cookie = ngx.req.get_headers()["Cookie"] or ""
         if string.match(cookie, "UserID") then  -- if we are logged in...
             ngx.exec("@rewrite")
         else
             local page = string.sub(ngx.var.request_uri, 2, -1)  -- get the page name without the leading slash
             local filename = page .. ".html"
             local f = io.open("/var/www/w/cache/" .. filename, "r")
             if f ~= nil then  -- if the file exists, close it and serve it directly
                 io.close(f)
                 ngx.header["x-wiki-cache"] = "via nginx"  -- headers to help you debug
                 ngx.exec("/cache/" .. filename)
             else
                 ngx.header["x-wiki-cache"] = "via mediawiki"
                 ngx.exec("@rewrite")
             end
         end
     ';
 }
  
 location @rewrite {
     rewrite ^/([^?]*)(?:\?(.*))? /index.php?title=$1&$2 last;
 }

Gestion du code

Voir aussi