Posts taggés cache

Installation et configuration de « Memcached » pour drupal 7

0

« Memcache » est un service autonome permettant de stocker tous types de variables, objets, etc. Mais principalement de mettre en cache les réponses des bases de données, en gérant les données et les objets en mémoire de façon à réduire le nombre d’appel à cette ou ces ressources.

 

Comment fonctionne  « memcache »

« Memcache » est un « moteur » qui stocke des valeurs sérialisées par des clefs prédéfinies par le développeur.

Exemple avec MySQL : votre code doit vérifier si vos données sont déjà stockées en cache avant de faire une requête MySQL en base. Si votre clef s’y trouve, vous évitez ainsi une connexion, gourmande en termes de ressources, avec la base de données.

Exemple de code :

$myCache = new Memcache;

$myCache->addServer('MEMCACHE_HOST', MONPORT);

$myCacheKey = 'ma_clef';

$myData = $myCache->get($myCacheKey);

if (!$myData) {
    $db = mysql_connect('MON_SERVEUR_MYSQL', 'LOGIN', 'PASSWORD');	
    mysql_select_db('MA_BASE',$db) ;

    $sql = "SELECT * FROM matable WHERE id = :id";
    $req = mysql_query($sql) or die('erreur mysql');
    $data = mysql_fetch_all($req);
    $myCache->set($myCacheKey, serialize($data));
    mysql_close();
}

 

Comment installer « memcache »

Installer le service « memcache »

sudo apt-get install memcached libmemcached-tools

 

Nous allons maintenant créer des sockets (« memcache » semble plus performant grâce aux sockets et cela permet de contrôler l’utilisation du cache beaucoup plus facilement).

sudo cp /etc/init.d/memcached /etc/init.d/memcached.bak

sudo vi /etc/init.d/memcached

 

Remplacez le script de démarrage par celui conseillé par la communauté drupal ; vous verrez qu’il permet la création de 13 sockets (http://drupal.org/node/1181968#comment-5855430) :

#! /bin/sh
#
# file: /etc/init.d/memcached
#
# chkconfig: - 55 45
# description:  The memcached-multi daemon is a network memory cache service. This script starts
#               memcached specifically for Drupal through Unix sockets (13 socket streams)
# processname: memcached-multi
# pidfile: /var/run/memcached/memcached.*.pid
#
# adapted from http://drupal.org/node/1181968
# by Coert van Gemeren (coert.vangemeren@dub.uu.nl) on 2012-03-30

PORT=11211
UDP=0
SOCKET=/tmp/memcached.socket
VAR=0
USER=memcached
MAXCONN=300
CACHESIZE=64
MEMCACHED=/usr/bin/memcached

RETVAL=0
prog="memcached"

start_instance() {
        if [ ! -e /var/run/memcached/memcached.$1.pid ] ; then
          echo "Starting $prog ($1)"
          OPTIONS="-d -s $3 -a 766 -L -t 8 -u $USER -m $2 -c $MAXCONN -P /var/run/memcached/memcached.$1.pid"
          start-stop-daemon --start --quiet --pidfile /var/run/memcached/memcached.$1.pid --make-pidfile --exec $MEMCACHED -- $OPTIONS
          RETVAL=$?
          [ $RETVAL -eq 0 ] && touch /var/lock/memcached/$1
        else
          echo "$prog ($1) already running: /var/run/memcached/memcached.$1.pid"
        fi
}

stop_instance() {
        if [ -e /var/run/memcached/memcached.$1.pid ] ; then
          PID=$(ps -ef|grep "/var/run/memcached/memcached.$1.pid"|grep -v "grep"|awk '{print $2}')
# FIXME! Not working yet
#          PID=$(cat /var/run/memcached/memcached.$1.pid)
          echo "Stopping $prog ($1)"
# FIXME! Not working yet
#          start-stop-daemon --stop --oknodo --pidfile /var/run/memcached/memcached.$1.pid --signal KILL --exec $MEMCACHED
          kill -9 $PID
          RETVAL=$?
          if [ $RETVAL -eq 0 ] ; then
            rm -f /var/lock/memcached/$1
            rm -f /var/run/memcached/memcached.$1.pid
          fi
        else
          echo "$prog ($1) not running: /var/run/memcached/memcached.$1.pid"
        fi
}

start() {
    # insure that /var/run/memcached has proper permissions
    if [ "`stat -c %U /var/run/memcached`" != "$USER" ]; then
        chown $USER /var/run/memcached
    fi
    # we start 13 socket streams for memcached
    start_instance default 64 /tmp/memcached.socket0;
    start_instance block 64 /tmp/memcached.socket1;
    start_instance content 64 /tmp/memcached.socket2;
    start_instance field 64 /tmp/memcached.socket3; #Field is new in D7, it is not yet supported in the memcache module reports page
    start_instance filter 64 /tmp/memcached.socket4;
    start_instance form 64 /tmp/memcached.socket5;
    start_instance menu 64 /tmp/memcached.socket6;
    start_instance page 64 /tmp/memcached.socket7;
    start_instance update 64 /tmp/memcached.socket8;
    start_instance views 64 /tmp/memcached.socket9;
    start_instance session 64 /tmp/memcached.socket10;
    start_instance users 64 /tmp/memcached.socket11;
    start_instance pbold 64 /tmp/memcached.socket12;
}

stop () {
    stop_instance default;
    stop_instance block;
    stop_instance content;
    stop_instance field;
    stop_instance filter;
    stop_instance form;
    stop_instance menu;
    stop_instance page;
    stop_instance update;
    stop_instance views;
    stop_instance session;
    stop_instance users;
    stop_instance pbold;
}

restart () {
        stop
        start
}

# See how we were called.
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  status)
        status memcached
        ;;
  restart|reload|force-reload)
        restart
        ;;
  *)
        echo $"Usage: $0 {start|stop|status|restart|reload|force-reload}"
        exit 1
esac

exit $?

 

Comment installer l’extension PHP « memcache »

sudo apt-get install php5-dev php-pear make
sudo pecl install memcache
sudo vi /etc/php5/conf.d/memcache.ini

 

Important : ne pas installer l’extension « memcached »  (extension plus récente que « memcache »). (Voir plus  bas « les détails de la configuration » pour plus d’explications)
Ajouter les lignes suivantes :

[memcache]
; Data will be transferred in chunks of this size
memcache.chunk_size = 32768
memcache.hash_strategy = consistent
memcache.default_port = 0
session.save_handler = memcache
session.save_path = "unix:///tmp/memcached.socket11:0?persistent=1&weight=1&timeout=1&retry_interval=15"

 

Pour plus explications sur les directives voir : http://www.php.net/manual/fr/memcache.ini.php

Il ne vous reste plus qu’à démarrer le service « memcache » et « apache » pour prendre en compte l’extension PHP « memcache ».

sudo /etc/init.d/memcached restart
sudo /etc/init.d/apache2 restart

 

Installer le module « memcache » pour drupal

Aller sur le module « memcache » de drupal. http://drupal.org/project/memcache
Télécharger la dernière version compatible pour drupal 7.
Copier le répertoire « memcache » dans le répertoire de vos modules contribués.
Allez sur la page d’installation des modules (admin/modules).
Cochez les deux modules ci-dessous :

memcached installation Drupal

Ensuite, il faut modifier votre fichier sites/default/settings.php :

$conf += array(
  'memcache_extension'           => 'Memcache',
  'show_memcache_statistics'     => 0,
  'memcache_persistent'          => TRUE,
  'memcache_stampede_protection' => TRUE,
  'memcache_stampede_semaphore'  => 15,
  'memcache_stampede_wait_time'  => 5,
  'memcache_stampede_wait_limit' => 3,
  'memcache_key_prefix'          => basename(realpath(conf_path())),
);

// We don't use chained memcached caching for sites cron, php-cli and install!
// memcache-session.inc has not successfully been ported to D7 yet!
if (isset($_SERVER['HTTP_USER_AGENT']) && !preg_match("/(?:cron\.php|install\.php)/", $_SERVER['REQUEST_URI'])) {
  if (isset($_SERVER['HTTP_HOST'])) {
    $conf += array(
      'cache_inc'        => './sites/all/modules/contrib/memcache/memcache.inc',
      'lock_inc'         => './sites/all/modules/contrib/memcache/memcache-lock.inc',
      'memcache_servers' => array(
         'unix:///tmp/memcached.socket0'  => 'default',
         'unix:///tmp/memcached.socket1'  => 'block',
         'unix:///tmp/memcached.socket2'  => 'content',
         'unix:///tmp/memcached.socket3'  => 'field',
         'unix:///tmp/memcached.socket4'  => 'filter',
         'unix:///tmp/memcached.socket5'  => 'form',
         'unix:///tmp/memcached.socket6'  => 'menu',
         'unix:///tmp/memcached.socket7'  => 'page',
         'unix:///tmp/memcached.socket8'  => 'update',
         'unix:///tmp/memcached.socket9'  => 'views',
         'unix:///tmp/memcached.socket10' => 'session',
         'unix:///tmp/memcached.socket11' => 'users',
      ),
      'memcache_bins'    => array(
         'cache'         => 'default',
         'cache_block'   => 'block',
         'cache_content' => 'content',
         'cache_field'   => 'field',
         'cache_filter'  => 'filter',
         'cache_form'    => 'form',
         'cache_menu'    => 'menu',
         'cache_page'    => 'page',
         'cache_update'  => 'update',
         'cache_views'   => 'views',
         'session'       => 'session',
         'users'         => 'users'
      ),
    );
  }
}

include_once('./includes/cache.inc');
// FIXME! We have to literally include memcache.inc already at this point
// otherwise D7 won't start (why? probably because php session.save_handler is memcached, but not sure)
include_once('./sites/all/modules/contrib/memcache/memcache.inc');

$conf['cache_backends'][] = 'sites/all/modules/contrib/memcache/memcache.inc';
$conf['cache_default_class'] = 'MemCacheDrupal'; //Any other cache bin goes to memcached

 

Détail de la configuration

La  variable « memcache_extension » : permet de choisir l’extension PECL désirée (« memcache » ou « memcached », notez l’ajout d’un d), l’extension « memcached » est plus récente et ajoute de nouvelles fonctionnalités. Cependant, l’extension « memcache » parait plus stable pour drupal et elle est préconisée par la communauté. Certains tickets sur drupal remontent des effets bords avec l’utilisation de « memcached ». Nous recommandons donc de suivre la communauté et d’utiliser l’extension « memcache ».

  • show_memcache_statistics : permet d’afficher des statistiques sur l’utilisation de « memcache » directement en bas des pages ; il faut mettre cette valeur à 0 ; vous pourrez de toute manière l’activer, pour un debuggage, directement depuis le backoffice drupal.
  • memcache_persistent : par défaut TRUE, la connexion ne sera pas fermée à la fin de l’exécution du script et par la fonction Memcache::close().
  • memcache_stampede_protection : lors de l’expiration du cache, stampede protection (littéralement protection d’une fuite en désordre) permet à un process d’envoyer l’ancien cache pendant qu’un autre process génère le nouveau cache. Cela permet donc d’avoir des performances accrues.
  • memcache_stampede_semaphore : valeur en secondes, permet d’éviter de mettre de nouveau en cache une même valeur pendant le laps de temps défini.
  • memcache_stampede_wait_time : valeur en secondes, temps d’attente maximum pendant la mise en cache.
  • memcache_stampede_wait_limit : valeur en entier, nombre d’essai maximum lors de la mise en cache.

IMPORTANT : « wait_time * wait_limit » doit toujours être inferieur au timeout du serveur web (pour apache et par défaut, le timeout serveur est de 30 secondes).

  • memcache_key_prefix : préfixe pour les clefs lors de la mise en cache d’une valeur, obligatoire lors d’une utilisation multi sites.
  • cache_inc : chemin vers le fichier memcache.inc du module « memcache ».
  • lock_inc : chemin vers le fichier « lock.inc » du module « memcache ».
  • memcache_servers : on indique nos 12 process « memcache » correspondants aux « bins memcache » ; vous devez mettre les mêmes valeurs définies dans le daemon 3.a).

Exemple :

         'unix:///tmp/memcached.socket0'  => 'default',
         'unix:///tmp/memcached.socket1'  => 'block',
         'unix:///tmp/memcached.socket2'  => 'content',
         'unix:///tmp/memcached.socket3'  => 'field',
         'unix:///tmp/memcached.socket4'  => 'filter',
         'unix:///tmp/memcached.socket5'  => 'form',
         'unix:///tmp/memcached.socket6'  => 'menu',
         'unix:///tmp/memcached.socket7'  => 'page',
         'unix:///tmp/memcached.socket8'  => 'update',
         'unix:///tmp/memcached.socket9'  => 'views',
         'unix:///tmp/memcached.socket10' => 'session',
         'unix:///tmp/memcached.socket11' => 'users',

 

  • memcache_bins : on indique à nos caches drupal, la connexion aux bins préalablement renseignés dans la variable memcache_servers.
    Normalement les bins  les plus utilisés sont : default, filter et menu.

 

IMPORTANT : Si le module « drupal memcache » n’arrive pas à se connecter au socket unix et à l’extension PECL Memcache, je vous conseille d’appliquer le patch disponible dans cette « issue »: http://drupal.org/node/1690130

 

Statistique d’utilisation de « memcache »

Maintenant que votre site utilise « memcache », vous devez vérifier que tout fonctionne correctement et que votre configuration est optimale ; pour cela aller sur la page :
http://monsite/admin/reports/memcache

 

memcached report

 

Vous retrouvez ici vos 12 process « memcache » (1 par onglet).
Vérifiez que la mémoire allouée est suffisante pour chaque process :

 

memcached Available Memory

 

Vérifiez également si vos variables sont bien cachés :

 

memcached - Variables cachés

 

Notre avis

Drupal peut-être très gourmand en requêtes SQL surtout si votre site n’est pas optimisé. « memcache » ne corrige pas ce problème d’optimisation mais permet de limiter les appels à MySQL.
Pour information, l’utilisation de socket n’est pas obligatoire mais permet très rapidement de voir ce qui est mis en cache ou non, directement depuis le backoffice DRUPAL ; vous pouvez ainsi améliorer votre système de cache en conséquence.

 

 

Alternative PHP Cache (APC)

0

Introduction

 

APC est la solution la plus simple pour optimiser les performances PHP.

Un script PHP doit être parsé, compilé et exécuté à chaque appel. APC permet de cacher les OPCode (structures de données en langage C), ce qui évite de parser et compiler le script à chaque appel.

 

Comment APC fonctionne-t-il ?

 

Lors du cycle de démarrage d’une requête, APC surcharge la fonction zend_compile_file() avec une fonction propre my_compile_file() :

  • Si my_compile_file () ne trouve pas de correspondance au script exécuté dans son cache (par défaut, APC utilise MMAP), APC appellera la fonction zend_compile_file() pour compiler le script. Sinon on passe directement à l’etape 2 ;
  • Les OPCode fournis seront ensuite stockés en mémoire partagée afin que les différents processus d’apache puissent les lire ;
  • APC copie ensuite les OPCodes directement dans les processus mémoire d’apache, pour permettre à zend d’exécuter le code du script demandé.

IMPORTANT : le cache APC sera entièrement vidé lors d’un redémarrage du serveur apache.

 

Comment installer APC ?

 

Sous linux

 

Nous partons de principe que nous sommes sur une installation par defaut. Si ce n’est pas le cas, modifiez les commandes ci-dessous en conséquence.

Sur une dedian ou ubuntu il faut taper les lignes suivantes :

 

sudo apt-get install php-apc

 

 Vérifiez que le fichier /etc/php5/conf.d/apc.ini  existe. Tapez la commande suivante :

 

sudo vi /etc/php5/conf.d/apc.ini

 

 Vérifiez que la ligne suivante est bien présente :

 

extension=apc.so

 

Si ce n’est pas le cas ajoutez-la dans le php.ini dans la partie Dynamic Extensions :

 

sudo vi /etc/php5/apache2/php.ini

 

 Ensuite il faudra modifier le fichier apc.ini ou php.ini :

 

sudo vi /etc/php5/conf.d/apc.ini 
sudo vi /etc/php5/apache2/php.ini

 

En fin de fichier ajoutez les lignes suivantes :

 

[APC]
apc.enabled=1

  

Ensuite tapez la ligne de commande suivante :

 

sudo /etc/init.d/apache2 restart

 

Sous windows

 

Si vous avez une installation de type wamp ou autre, la librairie ne fait surement pas partie de votre package.

Pour l’obtenir, allez sur le site suivant :

http://dev.freshsite.pl/php-accelerators/apc.html

Ou sur le site

http://downloads.php.net/pierre/

Récupérez la version correspondant à votre php ainsi qu’à votre windows .

Apres avoir dezippé votre dll, renommez-la en php_apc.dll

Copiez ensuite la dll dans le répertoire des extensions. Exemple pour wamp, vous trouverez les extensions dans le répertoire  [path_to_wamp]\bin\php\php5.x.x\ext

Lancez wamp pour prendre en compte votre librairie apc.

Désormais, il devrait apparaitre dans les extensions wamp.

 

apc-image1

 

 

Cochez l’extension php_apc.

Editez le fichier php.ini et ajouter les lignes suivantes en fin de fichier :

 

[APC]
apc.enabled=1

 

Redémarrez le serveur apache pour prendre en compte les dernières modifications.

 

Comment vérifier qu’APC est bien installé ?

 

Il suffit tout simplement d’afficher un phpinfo. Vous devriez voir le module apparaitre  comme ci-dessous :

apc-image2

 

Comment configurer APC ?

 

La documentation officielle (http://fr.php.net/manual/fr/apc.configuration.php) précise que la configuration APC par défaut est suffisante pour la plupart des installations.

Cependant, il y a deux paramètres à ajuster avec attention : apc.shm_size et apc.stat

 

apc.shm_size  et apc.stat 

 

  • apc.shm_size : ce paramètre correspond à la taille allouée pour la mémoire partagée.  Cette directive est par défaut à 32M, ce qui est trop peu, augmentez-la à 128M ou 256M, voire 512M si vous constatez une fragmentation trop importante ou une utilisation mémoire de vos caches à 100% ;
  • apc.stat : ce paramètre vérifie si les fichiers sont modifiés ou non avant d’utiliser le cache. Par défaut, cette directive est à 1. Si vous la passez à 0, aucun contrôle ne sera fait, et apc utilisera directement son cache, que le fichier soit modifié ou non. Le seul moyen de forcer APC à vérifier que des fichiers sont mis à jour, sera de redémarrer le serveur web ou de vider les caches via l’interface APC.
    Fortement conseillé pour les serveurs de production qui ont peu de mises à jour, et a contrario fortement déconseillé pour les serveurs de développement/intégration.

 

Prise en compte d’une directive par apc

 

Pour configurer une directive, il suffit simplement d’ajouter dans le php.ini ou dans apc.ini  le nom de la directive avec sa valeur ; par exemple :

 

[APC]
apc.enabled=1
apc.shm_size=256
apc.canonicalize=1
apc.ttl=0
apc.user_ttl=0
apc.rfc1867=1
…

 

Puis il suffit de redémarrer le serveur apache afin que vos directives soient prises en compte.

 

Quelques directives intéressantes

 

apc.canonicalize : permet de convertir tous les chemins relatifs que PHP va utiliser en chemins absolus

apc.ttl  : nombre de secondes pendant lesquelles le cache sera conservé, avant d’être régénéré à nouveau. Par défaut cette directive est à 0.

apc.write_lock : si vous avez un serveur avec de nombreux utilisateurs, apc peut compiler plusieurs fois le cache d’un même script. Cette directive permet donc de garantir qu’un seul processus compilera un script, les autres processus utilisant le même script n’utiliseront pas le cache au lieu d’être placé en file d’attente. Par défaut, cette directive est à 1

include_once_override : Directive expérimentale qui surcharge les fonctions include_once et require_once afin d’optimiser ces appels. A tester à vos risques et périls, d’après la documentation officielle à ce jour… Cependant si vous ne constatez pas d’effet de bord, vous pouvez gagner en performance.

apc.rfc1867 : gestionnaire de progression de téléchargement.

apc.num_files_hint : permet d’optimiser votre utilisation mémoire, en indiquant le nombre de fichiers distincts à mettre en cache. Vous ne pourrez pas configurer cette variable sans avoir laissé votre serveur tourner en production pendant un temps significatif. Par défaut elle est à 1000. Mettre 0 si vous avez un doute, ou patientez quelques temps pour augmenter ou diminuer cette valeur.

 

Comment installer la page d’administration APC ?

 

Sous linux , vous trouverez une page d’administration ici : /usr/share/doc/php-apc/apc.php

Il suffit de la copier sur votre serveur web :

 

sudo cp /usr/share/pear/apc.php.gz path/to/src/apc.php.gz
sudo gunzip /path/to/src/apc.php.gz
sudo vi /path/to/src/apc.php

 

Et de modifier ces deux lignes :

 

defaults('ADMIN_USERNAME','apc');       // Admin Username
defaults('ADMIN_PASSWORD','password');  // Admin Password - CHANGE THIS TO ENABLE!!!

 

Désormais la page est accessible . Par exemple : http://localhost/apc.php

 

 apc-image3

 

Pour vider les caches apc sans redémarrer le serveur, connectez vous en cliquant sur login, puis cliquez sur Clear opcode Cache.

 

apc-image4

 

 

Dans l’exemple ci-dessous, vous constatez que ce serveur dédie 256Mo en cache APC ce qui parait suffisant (il reste 87.8 Mo)

Les pages sont cachées à 100% (100% de Hits).

Si vous avez de nombreux « misses » et si la mémoire est utilisée à 100%, il faut augmenter votre valeur apc.shm_size :

  apc-image5

 

 

Mon avis

 

APC est très simple à installer. La configuration, une fois maitrisée, est également simple à mettre en œuvre. Les gains en performance sont tout de suite visibles. Donc mangez-en ! 🙂

C’est un outil qui permet rapidement de réduire des temps de réponses du serveur web, sans installation compliquée.

Pour les sites développés sous drupal, l’utilisation d’apc nécessite le module https://drupal.org/project/apc, il faudra penser à modifier votre fichier de configuration en conséquence (voir http://drupalcode.org/project/apc.git/blob_plain/refs/heads/7.x-1.x:/README.txt ).