Mise en cache des pages php : mon alternative hérétique !


Zecat
WRInaute accro
WRInaute accro
 
Messages: 11997
Inscription: 1 Mar 2005

Mise en cache des pages php : mon alternative hérétique !

Message le Ven Mai 13, 2011 11:43

HERETIQUE TU ES ... HERETIQUE TU RESTES !

Ben oui, comme d'habitude, il faut que je me fasse les trucs à ma sauce :!: J'ai lu l'enorme topic épinglé sur le sujet ... ainsi que les multiples variantes et alternatives proposées sur des sites linkés par ce topic ... Interessant mais usant ... vu la taille du topic ...

Ce que j'en retiens est que la mise en cache de page entière ne me convient pas :

1 - Ca implique que seule la version visiteur non inscrits/connecté est "cachable" et que donc seuls les visiteurs non inscrits sont concernés (tant sur le plan vitesse pour eux que sur le plan décharge de la bdd par eux). Les membres inscrits eux auront un affichage plus lent et se traduiront par une charge supérieure ... Pas glop pas glop ...

2 - Qu'il vous vienne à l'idée d'ajouter une "*" sur un élément présent sur toutes les les pages (style un onglet de plus dans la barre de menu ou même n'importe quel element statiques dans les pages) et hop c'est tout votre cache (ou toutes le spages ayant en commun cet élément statique) qui devient obsolète et part à la benne ... et devra être regénéré (soit massivement soit petit a petit au gré des affichages de page).

3 - Il est des contextes (mutu) ou la place sur disque est aussi comptée et donc mettre l integralité de la page en cache revient a stocker 100000 fois (si le site fait 100000 pages) la meme entete, la meme barre de menu, le meme footer etc etc. Et au final on en vient a régénerer sur le disque une version statique du site ... alors que dans le meme temps on va pinailler dans la bdd entre INT et LONGINT !!!! Pas très cohérent.

Parce que sur le fond, la mise en cache à pour objectif principal si j'ai pas sauté une marche de soulager la charge serveur au niveau des sollicitations de la base de données et, accessoirement de profiter d'un affichage plus rapide des pages puisque pas / ou moins de requete sql et moins de code de fabrication des eléments de mises en page.

Ayant posé ces postulat, j'en suis venu a commencer a me poser la question "quelle partie des pages mérite d'être mise en cache" ... Plutot qu'un long discours, deux exemples concret avec 1 page a l'url fixe "index.php" et une autre page "rewritée".

La page index de mon www :

Image
Url pour la voir en real : http://www.qui-est-le-meilleur.com

Si je tiens compte des constat ci-dessus, j'en arrive a considérer :

- toute la partie haute (cadre violet) non cachable (du pur statique donc zero economie mysql).
- la partie centrale (cadre vert) tout a fait dans la cible (y a deux requetes sql a gratter) et l'affichage ets le meme que l'on soit visiteur ou memebre inscrit.
- la partie basse (cadre rouge) mérite analyse car elle me consomme elle aussi 2 requetes sql la bougresse ... sauf que ca bouge tellement tout le temps (dès qu'un membre se gratte le nez ca fait bouger un truc la dedans) que l'on passerait plus de temps a supprimer/recréer le cache qu'à l'exploiter ... donc on l'oublie.
- Reste tout en haut d el'ecran la mention du connecté/non connecté. Par definition on l'oublie puisque l'on veut du cache "tout terrain" : inscrit / non inscrit / bot sans distinction.

UNe page de type histo :

Image
Url pour la voir en real : http://www.qui-est-le-meilleur.com/historique-2011-05-11.php

Si je choisi ce type de page, c'est que d'une part est elle simple dans son contenu (toujours plus facile dans le cadre d'explication ecrites) et que c'est une page avec paramètres et donc rewritée (contrairement a index.php ci-dessus). et cela a son importance pour la suite ... Mais non je plaisante : on se tappe royalement du rewriting (vou spouvez chager 10 fois vos régles dan sle htaccess sans impact sur la gestion du cache puisque ce ne sont pas des pages mais des "paquets de data" que l'on va mettre en cache ... et a qui on donne un petit nom deconnecté du rewriting (enfin en cohérence quand meme ...)

Selon la meme logique que ci-dessus on en vient a conclure que la seule partie cachable sera le cadre central (de toute façon c'est le seul qui consomme 1 requete mysql dans la page). En plus ce type de page a un gros avantage dans le cadre d'un cache : son cache est éternel ... puisque une fois une journée finie, ca ne bouge plus ...

Note : la on raisonne pour l'exempel sur une page qui consomme une micro requete sql et une seule donc l'impact sera faible mais le meme raisonnement s'applqiue sur un bloc necessitant quelques grosses requetes gourmandes avec jointure et tout et tout ...

MISE EN MUSIQUE

Bon ben ayant posé comme postulat que l'on ne gérait plus du cache de pages php mais du cache de morceau de pages, restait à le coder en essayant de mettre un place un truc facile a implanter avec un minimum de code (ma flemme est désormais bien connue donc autant y faire honneur) et offrant toute souplesse de choix pour chaque type de page ... Bref le beurre, les dihrams et la chamelière en prime ! Oui oui c'est une version locale que je viens d'inventer ...

Et finalement ca commence plutot bien puisque tout mon systeme de cache va reposer sur 5 petits script de 4 à 6 lignes ! Pourquoi faire plus si on peut faire moins ... Allez un peu de code lisible même par les phprank1 :

Cache_ecrire.php
Code: Tout sélectionner
<?php
   $cache_tampon = ob_get_contents();
   if(!is_dir($cache_dossier)) { mkdir ($cache_dossier); }
   $cache_ref = fopen ($cache_chemin, "w+");
   fputs ($cache_ref, $cache_tampon);
   fclose ($cache_ref);
?>

Ca va pas trop fatigué le chat ? nan nan ca va ...

Cache_lire.php
Code: Tout sélectionner
<?php
      $cache_dossier=$_SERVER["DOCUMENT_ROOT"].'/CACHE_'.$cache_version.'/';
      $cache_document=$cache_nom.$cache_param.'.php';
      $cache_chemin=$cache_dossier.$cache_document;
      if(file_exists($cache_chemin))
      {
         echo("."); // debug : signalement debut lu dans cache
         readfile($cache_chemin);
         echo(".."); // debug : signalement fin lu dans cache
         $cache_trouve=true;   
      }
      else { $cache_trouve=false; }
?>


Ouai là non plus pas de callosités sous les indexes !

Cache_detruire.php

Code: Tout sélectionner
<?php
      $cache_dossier=$_SERVER["DOCUMENT_ROOT"].'/CACHE_'.$cache_version.'/';
      $cache_document=$cache_nom.'.php';
      $cache_chemin=$cache_dossier.$cache_document;
      if(file_exists($cache_chemin))
      {
         echo("Suppression du cache : ".$cache_document."<br>");
         $cache_ouverture = opendir ($cache_dossier);
            unlink ($cache_chemin);
           closedir ($cache_ouverture);
      }
?>


Note : ici on peut choisir d'autres options (ne pas detruire mais réécrire vide), ou encore ne rien toucher à part ecraser le premier octet du document avec une "*" d'invalidation (ultra vite ecrit et vite testé ...). Perso en prod je pense que c'est cette option que je choisirai ... il suffira de changer la façon de tester dans cache_lire ...

Arrête zecat, tu frises la suractivité et l'usure prématurée du clavier ...

Cache_affiche.php

Code: Tout sélectionner
<?php
      include("cache_lire.php"); // on regarde si il existe et on l'affiche si oui
      if(!$cache_trouve) // si pas de cache trouvé
      {
         echo("<u>.</u>"); // debug : signalement debut fab cache
         ob_start(); // debut mise en tampon
            switch ($cache_nom)
            {
               case 'cache_aaaaaa_1':
                  include("aaaaaa_cache_fab_1.php"); // fabrication morceau 1 de page aaaaaa
                  break;


               case 'cache_bbbbbb_1':
                  include("bbbbbb_cache_fab_1.php"); // fabrication cadre central page bbbbbb
                  break;
            }

            include("cache_ecrire.php"); // on ecrit le cache sur disque
         ob_end_clean(); // arret mise en tampon
         echo($cache_tampon); // on affiche ce qu'on vient de fabriquer
         echo("<u>..</u>"); // debug : signalement fin fab cache
      }
?>
Houla vite une chaise longue ...

cache_impacter.php

Code: Tout sélectionner
<?php
   $cache_dossier=$_SERVER["DOCUMENT_ROOT"].'/CACHE_'.$cache_version.'/';
   if(is_dir($cache_dossier))
   {   
      $ouverture = opendir ($cache_dossier);
      echo("Impact cache : "); // echo de debug
      foreach($tab_cache_impact as $cache_document)
      {
         echo($cache_document."/"); // echo de debug
         $cache_chemin=$cache_dossier.$cache_document;
         if(file_exists($cache_chemin)) { unlink ($cache_chemin); }
      }
      closedir ($ouverture);
   }      
?>


Voila c'est tout. Toutes les routines sont en place.

MISE EN APPLICATION SUR LA PAGE INDEX.PHP

Son code (avant gestion cache) est simple (j'ai juste renommé les scripts pour la clarté mais c'est tout) :

Code: Tout sélectionner
<?php
   include ("entete.php");
   include ("menu.php");
                include ("presentation.php");
                include ("actus_ajouts.php");
                include ("cadre_qui.php");
   include("affiche_pied_haut.php");
?>


On a vu que la seule partie de la page qui nous intéresse au titre de la mise en cache est actus_ajouts ... je modifie donc cette page ainsi :

Code: Tout sélectionner
<?php
   include ("entete.php");
   include ("menu.php");
                include ("presentation.php");
               
                       $cache_nom="cache_index_1";
                       include("cache_affiche.php");

                include ("cadre_qui.php");
   include("affiche_pied_haut.php");
?>


et on mets actus_ajouts dans le switch de cache_affiche à la place de aaaaaa ..
(le premier case) :

Code: Tout sélectionner
case 'cache_index_1:
     include("actus_ajouts.php");


En gros je décide de donner un zouli petit nom à ce bloc et je l'appelle, notez l'originalité et la recherche "cache_index_1" (1 c'est parce que rien n'interdit d'avoir demain un autre bloc cache dans cette même page ... on le nommera surement ... cache_index_2 !

VOILA C'EST FINI ... OU PRESQUE ...

On lance désormais index.php sur notre navigateur ... cadre_affiche est lancé. il regarde si il a le nom demandé en stock (cache_index_1) ... Nada ! Donc il passe en mode "tampon" et execute le code normal "actus_ajouts.php" puis le balance sur le disque (cache_ecrire) et l'affiche normalement. Les encadrements par "." et ".." c'est juste pour voir les scripts agir en phase debug. On vient donc de génerer le cache du morceau voulu (que le visiteur soit un bot, un visiteur ou un inscrit). On pourra juste ajouter un if (gooogloubot) pas d'ecriture cache (histoire de travailler sa courbe dans GWT).

Maintenant votre voisine de palier arrive aussi sur cette page, ca execute cache_affiche, qui trouve le cache demandé et donc cache_lire lit et affiche le morceau voulu avec "readfile($cache_chemin);" et saute le reste.

Pour la page historique c'est le meme principe sauf que comme c'est une page avec un parametre en entrée le code devient :

La page avant :

Code: Tout sélectionner
<?php
   ...

                include ("historique_liste.php");

                ...
?>


La page apres :

Code: Tout sélectionner
<?php
   ...
                       $cache_param="_".date('Ymd');
                       $cache_nom="cache_historique_1";
                       include("cache_affiche.php");

                ...
?>


Vous noterez la seule différence avec la page index : on passe une valeur date du jour dans $cache_param (pas mis direct dans cache_nom pour que l'on reste dans un seul case au niveau du switch. Et le second switch de case_affiche :

Code: Tout sélectionner
case 'cache_historique_1':
     $date_histo=$cache_param;
     include ("historique_liste.php");


Voila nous disposons d'un systeme de cache permettant de couvrir les pages a url fixe et les pages avec paramètres ... en prenant en cache dans les pages le ou les paquets qui nous intéressent ...

PAS DE DUREE DE VIE A PRIORI

Ben non ! Un morceau en cache n'a aucune raison de sortir de sa cachette (ah c'est malin ...) tant qu'on le laisse dormir ... Certains caches seront éternels (cf historiques) et d'autres à durée de vie plus courte (cf index). Et donc toute la question est : qui va être autorisé à décider que tel morceau de cache est obsolète et doit mourir ... Et je reconnais que c'est la que ca devient un peu plus casse-machins à formaliser de façon aussi simple et tout terrain ... Enfin tout est relatif puisque c'est le script cache_impacter.php qui se chargera du truc ...

MISE A JOUR DU CACHE

Le principe est tout simplement pour chaque fonction (les post via formulaire en général) de se demander "quel(s) cache(s) cette action doit elle impacter" (impacter ca veut dire supprimer !).

J'ai donc un en validation de mon formulaire d'ajout de nouveaux prestataires un submit qui lance "prestataire_ajout_pos.php". Son allure est en gros (je saute les etapes de verif et l'enrobage de filtrage etc) :

Code: Tout sélectionner
<?php

include("sql_base_open.php");
     include("sql_prestataire_add.php");
include("sql_base_close.php");

?>


Cette fonction va avoir un impact sur le cache index et sur le cache histo du jour concerné ... je vais donc ajouter quelques lignes à mon script qui devient :

Code: Tout sélectionner
<?php

include("sql_base_open.php");
     include("sql_prestatire_add.php");
include("sql_base_close.php");

   // ----- tableau des impacts sur cache de la fonction ajouter prestataire
   $tab_cache_impact=array();
   $tab_cache_impact[]='cache_index_1.php'; // le cadre derniers ajouts
   $tab_cache_impact[]='cache_historique_1'.'_'.date('Ymd').'.php'; // la page histo du jour
   include("cache_impacter.php");
?>


Et donc dès lors qu'un utilisateur ajoute une fiche, cache_impacter va se charger de faire le menage ...

Note : j'ai mis la page histo juste pour la comprehension parce que en fait, dans ce cas particulier, je vais en amont tout simplement ne pas chercher de cache lorsque l'on affiche la page du jour courant ... donc aucun besoin d'impacter avec une saisie forcément dans le jour courant ...

Voila y a tout ...

LA VERSION DE CACHE

J'allais oublier ... Vous aurez noté que l'on range les caches non pas dans un dossier CACHE mais CACHE_V01 (si $cache_version a été initalisée avec "V01"). C'est tout simplement pour faciliter une opération de purge totale du cache (pour telle ou tele raison, peut importe).

Il suffit donc de changer la valeur de $cache_version en "V02" et tout le cahe se déroute vers un nouveau dossier (vide) CACHE_V02 ... Ce qui laisse tout loisirs de virer un peu plus tard sans stress le dossier CACHE_V01 en 2 clics via son cpanel par exemple ...



C'est tout chaud en cours de test (fonctionnel ... je vous aurais pas mis du code qui plante !) et donc si vous avez des remarques ou suggestions ... (y a surement des petites optimisations de code ou de méthodologie que j'ai sauté ....).

L'intéret : c'est tout léger, sans impact au niveau rewriting et très souple pour s'adapter à de multiples cas de figure en englobant des parties plus ou moins grande des pages dans les caches, tout en ne stockant pas de trop gros volumes sur le disque du serveur ... et ca se met en place en quelques minutes sans se poser de question : on pose les 5 scripts à la racine de son site et on peut commencer a "cacher" ses premier morceaux de page ... Enfin moi je le sens ainsi :wink:

Ouf je suis au bout du topic ... allez hop clic sur ENVOYER ! Faites pas gaffe aux fautes de frappes, vu la longueur ...


finstreet
WRInaute accro
WRInaute accro
 
Messages: 16999
Inscription: 10 Juil 2005

Re: Mise en cache des pages php : mon alternative hérétique !

Message le Ven Mai 13, 2011 13:43

Sincèrement... j'ai lu que les dix premières lignes :) Perso j'ai un cache global dont je gère la réactualisation, et un cache spécifique (un champ dans une table) où la réactualisation est encore moins fréquente (liens internes)


Zecat
WRInaute accro
WRInaute accro
 
Messages: 11997
Inscription: 1 Mar 2005

Re: Mise en cache des pages php : mon alternative hérétique !

Message le Ven Mai 13, 2011 13:49

finstreet a écrit:Sincèrement... j'ai lu que les dix premières lignes :)

Ca limite le débat :mrgreen:


finstreet
WRInaute accro
WRInaute accro
 
Messages: 16999
Inscription: 10 Juil 2005

Re: Mise en cache des pages php : mon alternative hérétique !

Message le Ven Mai 13, 2011 13:54

Zecat a écrit:
finstreet a écrit:Sincèrement... j'ai lu que les dix premières lignes :)

Ca limite le débat :mrgreen:


Bah non. On a le même constat sur les dix premières lignes : ne pas défavoriser le membre inscrit par rapport au non inscrit :)

mitchum
WRInaute discret
WRInaute discret
 
Messages: 237
Inscription: 18 Fév 2004

Re: Mise en cache des pages php : mon alternative hérétique !

Message le Ven Mai 13, 2011 15:38

hey sinon Zecat pourquoi tu te prends la tête, il y a un truc qui s’appelle ESI include et qui marche plutôt bien avec varnish !
http://www.varnish-cache.org/trac/wiki/ESIfeatures

je l'ai mis en place sur un site wordpress aveec pas mal de plugin (et pas forcément optimisé) et quand tu fais un bench tu gagne 4000% !!!
Bon une fois les vrais membres dessus ca change un peu, mais on a gagné quelques parts Gandi (4)...

Comment ca tu veux juste evoluer de rank php ^^

Dolph
WRInaute impliqué
WRInaute impliqué
 
Messages: 631
Inscription: 1 Mar 2011

Re: Mise en cache des pages php : mon alternative hérétique !

Message le Ven Mai 13, 2011 15:39

Disons qu'il faut différencier l'approche des pages caches.
1 - Les pages rarement consultés
2 - Les pages prisées

Pour le 1, à part si la page demande une chiée de requêtes qui écroulent le server durant 5s, aucun interêt du cache.

Pour le 2 :
- Les pages qui ne changent que très rarement.
- Les pages qui changent peu, mais ont gavé de requêtes.
- Les pages qui changent tout le temps et ont aussi gavé de requêtes.

C'est pas une solution, juste une direction de recherche. :-)


Zecat
WRInaute accro
WRInaute accro
 
Messages: 11997
Inscription: 1 Mar 2005

Re: Mise en cache des pages php : mon alternative hérétique !

Message le Ven Mai 13, 2011 15:42

mitchum a écrit:hey sinon Zecat pourquoi tu te prends la tête, il y a un truc qui s’appelle ESI include et qui marche plutôt bien avec varnish !
http://www.varnish-cache.org/trac/wiki/ESIfeatures

je l'ai mis en place sur un site wordpress aveec pas mal de plugin (et pas forcément optimisé) et quand tu fais un bench tu gagne 4000% !!!
Bon une fois les vrais membres dessus ca change un peu, mais on a gagné quelques parts Gandi (4)...

Comment ca tu veux juste evoluer de rank php ^^

J eme suis pas cassé le fion a ecrire un forum pour utiliser un truc pas écris by me pour la gestion du cache :mrgreen:


YoyoS
WRInaute accro
WRInaute accro
 
Messages: 3835
Inscription: 14 Sep 2006

Re: Mise en cache des pages php : mon alternative hérétique !

Message le Ven Mai 13, 2011 15:50

Au prochain épisode, Zecat vous réinventera un nouveau concept: La messagerie privée :D


Zecat
WRInaute accro
WRInaute accro
 
Messages: 11997
Inscription: 1 Mar 2005

Re: Mise en cache des pages php : mon alternative hérétique !

Message le Ven Mai 13, 2011 15:54

YoyoS a écrit:Au prochain épisode, Zecat vous réinventera un nouveau concept: La messagerie privée :D

Toujours aussi aimable Yoyos :roll:

mitchum
WRInaute discret
WRInaute discret
 
Messages: 237
Inscription: 18 Fév 2004

Re: Mise en cache des pages php : mon alternative hérétique !

Message le Ven Mai 13, 2011 16:09

et sinon pourquoi utiliser apache alors, un catpache c'est pas mieux ? ahah
quiestlemeilleurapprentiphp.com/zecat/motive-abloc/
:) :) :)


Zecat
WRInaute accro
WRInaute accro
 
Messages: 11997
Inscription: 1 Mar 2005

Re: Mise en cache des pages php : mon alternative hérétique !

Message le Ven Mai 13, 2011 16:22

YoyoS a écrit:Au prochain épisode, Zecat vous réinventera un nouveau concept: La messagerie privée :D

Tu vois je suis "sympa" avec toi, je te brosse dans le sens du poil :

http://forum.webrankinfo.com/brainstorming-truc-titille-sur-les-dans-l ... 42515.html

Il te suffit de demander :lol:


YoyoS
WRInaute accro
WRInaute accro
 
Messages: 3835
Inscription: 14 Sep 2006

Re: Mise en cache des pages php : mon alternative hérétique !

Message le Ven Mai 13, 2011 22:54

J'ai eu aussi la flème de lire tout ton post cpour ça aussi :D Désolé pour la boutade :P


Zecat
WRInaute accro
WRInaute accro
 
Messages: 11997
Inscription: 1 Mar 2005

Re: Mise en cache des pages php : mon alternative hérétique !

Message le Lun Mai 16, 2011 10:49

Ce topic en tête des reco ! Je ne penais pas que mes 5 petits scripts allaient plaire autant :wink:


Julia41
WRInaute passionné
WRInaute passionné
 
Messages: 1765
Inscription: 31 Aoû 2007

Re: Mise en cache des pages php : mon alternative hérétique !

Message le Lun Mai 16, 2011 12:59

Bon, 2/3 trucs que je trouve moyen, tu fais par exemple sur chaque requête :
if (!is_dir(ton rep de cache...
Ca fait une lecture de disque pour rien (très performance killer si fort traffic au niveau des accès disque).
Tu fais la même chose sauf que au lieu de mettre sur le disque tu mets en RAM (memcache) et tu gagnes x100 pour la vitesse de cache/affichage ;)


Zecat
WRInaute accro
WRInaute accro
 
Messages: 11997
Inscription: 1 Mar 2005

Re: Mise en cache des pages php : mon alternative hérétique !

Message le Lun Mai 16, 2011 13:33

Julia41 a écrit:Bon, 2/3 trucs que je trouve moyen, tu fais par exemple sur chaque requête :
if (!is_dir(ton rep de cache...
Ca fait une lecture de disque pour rien (très performance killer si fort traffic au niveau des accès disque).
Tu fais la même chose sauf que au lieu de mettre sur le disque tu mets en RAM (memcache) et tu gagnes x100 pour la vitesse de cache/affichage ;)

Merci julia, c'est exactement le type de suggestion que j'attendais de ce topic ... je vais intégrer la chose et refournir les 5 scripts adaptés (puisque manifestement certains les intègrent déjà ...). Et à part cela, tu dis 2/3 trucs .. tu peux developper svp.

Mise en cache des pages php : mon alternative hérétique !

Si vous avez aimé cette discussion, partagez-la sur vos réseaux sociaux préférés :

Lectures recommandées sur ce thème :



Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 4 invités