Publié le 16/12/2013
Auteur Fobec
Réseaux sociaux
0 partages
0 tweets
3 plus
0 commentaires

Cache avec une archive ZIP

Comme nous l'avons vu précédemment dans l'article Cache Fichier avec compression, la sauvegarde de page HTML sous forme de fichier présente la faiblesse de générer un grand nombre de fichier. La maintenance de ce système est difficile à effectuer, en particulier le transfert du contenu du cache vers un autre poste.
Comment regrouper les fichiers dans des paquets ?
Un zip bien sur ! l'idée est d'utiliser une archive Zip pour placer de 5 000 à 10 000 fichiers. L'avantage est de réduire considérablement le nombre de fichier cache et de profiter de la compression automatique du format Zip.

Lire et enregistrer un cache compressé

Regroupons les fonctions de sauvegarde et de lecture de page HTML dans une class PHP. Nous présenterons les fonctions en détail dans al suite de l'article.
note: la class a été mise en place sur le site Fobec.com de mai à septembre.
<?php
/**
 * Systeme de cache fichier avec une archive ZIP
 * @see http://www.fobec.com/php5/1137/cache-avec-une-archive-zip.html
 * @copyright (c) 12/2013, Fobec
 */
class HtmlCacheZip {
 
    private $zipfilepath = '';//chemin de l'archive zip
 
    private $createIfnotExists=false;//créer une nouvelle archive zip
 
    private $lastError = '';//Dernière erreur rencontrée
 
    /**
     * Constructeur
     * @param type $archivePath nom de l'archive zip
     * @param type $createArchive forcer la creation de l'archive si elle n'existe pas
     */
    public function __construct($archivePath,$createArchive = FALSE) {
        $this->zipfilepath = $archivePath;
        $this->createIfnotExists=$createArchive;
    }
 
    /**
     * Retourner la dernière erreur
     * @return String
     */
    public function getLastError() {
        return $this->lastError;
    }
 
    /**
     * Ajouter un String dans le zip
     * @param type $string contenu
     * @param type $localname nom du contenu
     * @return boolean succès de l'ajout
     */
    public function writeString($string, $localname) {
        $za = new ZipArchive;
        if (!file_exists($this->zipfilepath) && $this->createIfnotExists == TRUE) {
            $res = $za->open($this->zipfilepath, ZipArchive::CREATE);
        } else {
            $res = $za->open($this->zipfilepath);
        }
        if ($res === TRUE) {
            $za->addFromString($localname, $string);
            $za->close();
            return TRUE;
        } else {            
            $this->lastError = 'Invalid or unitialized Zip object on '.$this->zipfilepath;
            //$this->lastError=$za->getStatusString(); //<- it does not work with php 5.2            
            return FALSE;
        }
    }
 
    /**
     * Ajouter un fichier au zip
     * @param type $filename nom du fichier à ajouter
     * @return boolean succès de l'ajout
     */
    public function writeFile($filename) {
        $localname = basename($filename);
        $za = new ZipArchive;
        if (!file_exists($this->zipfilepath) && $this->createIfnotExists == TRUE) {
            $res = $za->open($this->zipfilepath, ZipArchive::CREATE);
        } else {
            $res = $za->open($this->zipfilepath);
        }
        if ($res === TRUE) {
            $za->addFile($filename, $localname);
            $za->close();
            return TRUE;
        } else {            
            $this->lastError = 'Invalid or unitialized Zip object on '.$this->zipfilepath;
            //$this->lastError=$za->getStatusString(); //<- it does not work with php 5.2            
            return FALSE;
        }        
    }
 
    /**
     * Lire le contenu d'un fichier du zip
     * @param type $localname
     * @param type $maxage
     * @return null|boolean null en cas de cache périmé, false en cas d'erreur
     */
    public function readAsString($localname, $maxage) {
        $za = new ZipArchive();
        $res = $za->open($this->zipfilepath);
        if ($res === TRUE) {
            $rows = $za->statName($localname);  
            if ($rows != FALSE && (time() - $rows['mtime']) < $maxage) {
                return $za->getFromName($localname);
            } else if ($rows != FALSE ) {
                return NULL;
            }
            $za->close();
        } else {            
            $this->lastError = 'Invalid or unitialized Zip object on '.$this->zipfilepath;
            //$this->lastError=$za->getStatusString(); //<- it does not work with php 5.2            
            return FALSE;
        }   
    }
 
    /*     * *************************************************************************
     * Duree de vie 1 heure 1 x 60 x 60
     * ************************************************************************* */
 
    const LIFE_ONEHOUR = 360;
    /*     * *************************************************************************
     * Duree de vie 1 journée 24 x 60 x 60
     * ************************************************************************* */
    const LIFE_ONEDAY = 86400;
    /*     * *************************************************************************
     * Duree de vie 1 semaine 7 x 24 x 60 x 60
     * ************************************************************************* */
    const LIFE_ONEWEEK = 604800;
    /*     * *************************************************************************
     * Duree de vie 1 mois 30 x 24 x 60 x 60
     * ************************************************************************* */
    const LIFE_ONEONTH = 2592000;
}
?>

Enregistrer le contenu d'une page HTML

Le code source PHP suivant effectue les opérations suivantes:
new HtmlCacheZip(): ouverture de l'archive zip nommée 123.zip. La valeur TRUE autorise la class à créer une nouvelle archive si elle n'existe pas encore,
writeString(): ajout dans l'archive d'une variable de type String. Le second paramètre fixe le nom du contenu dans l'archive zip,
getLastError(): en cas d'erreur, la fonction retourne le dernier message d'erreur.
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/htmlcachezip.php';
 
$htmlCacheZip=new HtmlCacheZip($_SERVER['DOCUMENT_ROOT'].'/123.zip',TRUE);
$success=$htmlCacheZip->writeString("code source de la page html", 'index.html');
if (!$success) {
   echo $htmlCacheZip->getLastError(); 
}
?>
Comment ajouter un fichier ?
Le principe est identique, il suffit d'appeler $htmlCacheZip->writeFile() en place de writeString(). Le premier paramètre représente le nom complet du fichier à ajouter.

Lire le contenu à partir du cache zip

La lecture du contenu HTML à partir du cache est soumise à deux conditions:
- sauvegarde: le code source a été correctement ajouté dans un premier temps,
- validité cache: l'age des données est inférieur à la validité du cache que l'on s'est fixée.
<?php 
require_once $_SERVER['DOCUMENT_ROOT'] . '/htmlcachezip.php';
 
$htmlCacheZip = new HtmlCacheZip($_SERVER['DOCUMENT_ROOT'] . '/123.zip');
$html = $htmlCacheZip->readAsString('index.html', HtmlCacheZip::LIFE_ONEDAY);
if ($html == FALSE) {
   //erreur lors de la lecture
    echo $htmlCacheZip->getLastError();
} else if ($html == NULL) {
   //cache périmé 
} else {
    //Cache valide
    //echo html
} 
?>

Comment déterminer l'age du cache ?
Dans une archive ZIP, chaque fichier est accompagné d'une entête dont on peut lire les propriétés avec ZipArchive::statName(). L'index ['mtime'] retourne la date d'ajout du fichier au format Unix.

Force et faiblesse du cache ZIP

Ce système de cache a été mis en place sur les adresses IP locales de type 192.168.x.x. En terme de contenu, la rubrique compte env. 4000 fichiers. Les temps de réponse sont très bons en comparaison aux requetes à partir de MySql.

(force) maintenance: l'ensemble du contenu est regroupé dans quelques archives ZIP. Il est très facile de déplacer le cache vers un autre poste de travail ou encore de mettre à jour certaines parties du cache,
(faiblesse) performance: lorsque le nombre de fichiers atteint 3000, j'ai eu l'impression que le temps de chargement avait tendance à s'allonger,
(faiblesse) accès concurrent: comment est gérer l'accès simultané à la même ressource ? Bien qu'aucun test n'ait été effectué en la matière, le système d'archive zip parait bancale. De plus, aucun mécanisme n'est prévu pour les grosses montée en charge du trafic.

Ajouter un commentaire

Les champs marqués d'un * sont obligatoires, les adresses emails se sont pas publiées.

A lire aussi

Réseaux sociaux
Présentation de l'article
Catégorie
php5 - class
Mise a jour
16/12/2013
Visualisation
vu 2950 fois
Public
Internaute
Auteur de la publication
Fobec
Admin
Auteur de 261 articles
|BIO_PSEUDO|
Commentaires récents

Publié par iliass dans CMS

aebgksdktu hsmu yailsh iliass jqd ou azmwt wa ikraame

Publié par pgts09 dans tuto

Bonjour,
Felicitations pour ce tuto simple, et qui semble repondre exactement ce que je cherchais !
Malheureusement je n'arrive pas faire fonctionner, voici ce que donne mon essai : J'ai pourt...

Publié par Fobec dans php5

a priori il manque simplement le R dans le nom de la constante
PDO::ATTR_ERRMODE en remplacement de PDO::ATT_ERRMODE

Publié par Souti dans php5

Merci pour ce code. Trs utile.

Pour mon cas, il a fallu que j'ajoute une } avant ?> le pour fermer le for each.

Publié par Anis Hidouri dans java

Très bon exemple même si le drivers jdbc comporte quelques erreurs !!!