Posts taggés drupal

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.

 

 

drupal

Fonctionnement du multilinguisme dans le CMS Drupal 7 (2 sur 2)

0

Cet article fait suite à l’article : http://blog.webnet.fr/multilinguisme-avec-drupal-7-partie-1/

 

Les différentes méthodes de traduction

La traduction : node-level

 

Ce niveau de traduction est fourni par le module présent dans le cœur de Drupal : « Content Translation ». Il a pour caractéristique de créer un nouveau nœud à chaque traduction et d’associer les nœuds entre eux grâce à des identifiants de traduction appelés « tnid ». Afin de mieux comprendre ce concept nous allons prendre un exemple concret. Tout comme la précédente traduction, il faut spécifier à Drupal la caractéristique multilingue souhaitée aux types de contenu concernés : ici elle est activé avec la « traduction ».

drupal-multilingue-image-09

Lorsque l’option multilingue avec traductions est activée il est possible de sélectionner la langue d’un nœud lors de sa création ou de son édition. Si une langue est définit, un nouvel onglet « Traduire » apparait.

 

drupal-multilingue-image-10

drupal-multilingue-image-11

 

L’ajout d’une traduction engendre la création d’un nouveau nœud. Le tableau ci-dessous présente les données enregistrées en base :

Identifiant du nœud

Langue

Identifiant de traduction

ID – nœud FR

FR

ID – nœud FR

ID – nœud EN

EN

ID – nœud FR

Le précédent tableau est donc construit de la façon suivante : Drupal recherche l’ensemble des nœuds ayant pour identifiant de traduction, l’identifiant du nœud courant et applique le suffixe « (source) » au nœud possédant son identifiant en « identifiant de traduction ».

Les nœuds étant indépendants les uns des autres, si la source est supprimée, le nœud traduit possédant l’identifiant le plus petit devient source à son tour. Dans le cas d’une erreur de suppression pas de panique ! Le module « Multilingual content » vient à votre secours car il permet de rattacher via un champ d’auto complétion, un nœud existant comme traduction possible :

 drupal-multilingue-image-12

L’avantage de la traduction node-level est qu’elle permet de notifier à l’utilisateur qu’une traduction est périmée ou que l’ensemble des traductions d’une source sont périmées. Pour cela il suffit de se rendre sur l’édition d’un contenu et de cocher la case située dans les paramètres de traduction :

drupal-multilingue-image-13

(Traduction non-source)

L’état des traductions est visible en se positionnant sur l’onglet « Traduire » d’un des nœuds. Pour les curieux sachez que cet état est défini dans le champ « Translate » de la table « node ».

drupal-multilingue-image-15

 Les avantages de cette méthode sont les suivants :

  • Les nœuds peuvent être configurés indépendamment les uns des autres ;
  • Elle permet la création d’un menu asymétrique par langage car les items de menu sont saisis sur la page d’édition des nœuds ;
  • Cette méthode étant celle présente dans le corps elle est plus adaptée pour les fonctionnalités natives basées sur les nœuds telles que la recherche ;
  • Elle notifie l’utilisateur lorsqu’une traduction doit-être mise à jour ;

 

Les inconvénients de cette méthode sont les suivants :

  • Tous les éléments constituant un nœud sont spécifiques à un langage : si un nœud a la même image, quelle que soit sa traduction, l’image devra être dupliquée autant de fois que de traductions;
  • Il est nécessaire de synchroniser les données entre les nœuds ;
  • Cela génère un nombre importants de nœuds ;
  • Ne fonctionne que pour les nœuds ;

 

La translation : field-level

 

Ce niveau de traduction est fourni par module contributeur : « Entity Translation ».

Il permet la traduction du contenu par champ. Afin de mieux comprendre ce concept nous allons, là-aussi prendre un exemple concret. Nous allons directement aller spécifier à Drupal la caractéristique multilingue souhaitée aux types de contenu concernés : « Enabled, with field translation ».

drupal-multilingue-image-16

La traduction se faisant par champ, il est désormais nécessaire de spécifier quel champ doit-être traduit. L’avantage c’est que l’on peut garder des champs communs aux différentes langues.

 

drupal-multilingue-image-17

Attention toutefois le titre n’est pas un champ mais une propriété. Pour traduire cette propriété il vous faut activer le module « Title » qui offre la possibilité de remplacer la propriété par un champ d’instance personnalisable. Cette manipulation se fait toujours au niveau du type de contenu.

 

drupal-multilingue-image-18

 

Une fois ces manipulations effectuées, vous verrez apparaitre sur la page de création ou d’édition d’un nœud une annotation à côté des labels de certains champs : « (toutes les langues) ». Cette dernière précise que le champ concerné est unique pour l’ensemble des contenus traduits. Dans le cas contraire votre champ est spécifique à la langue courante (qui apparait entre crochets suffixé au titre de la page).

L’interface vous permet de passer d’une langue à l’autre grâce aux onglets situés en haut à droite de la page, et vous avez aussi accès à l’onglet « Traduire ».

 

drupal-multilingue-image-19

 

Faites attention à ne pas confondre avec l’autre méthode. Il n’y a pas de notion de duplication ici, l’ensemble des traductions d’un nœud sont rattachées à un même identifiant. Si vous supprimez le nœud, toutes vos traductions seront perdues.

« Entity Translation » offre plusieurs options de configuration dont les possibilités de :

  • Choisir une langue par défaut
  • Masquer le sélecteur de langue ;
  • Verrouiller la langue d’un contenu une fois que ce dernier est créé ;
  • Cacher les éléments partagés sur les pages de traductions afin d’éviter les confusions ;

 

drupal-multilingue-image-20

 

Enfin, le plus intéressant reste que cette méthode s’applique aux entités et non aux nœuds seuls. En effet, tout dans Drupal peut être vu comme une entité ce qui n’est pas le cas pour les nœuds. Ainsi il est possible de traduire par champs les commentaires, les nœuds, les termes de taxonomie et les utilisateurs.

 

Les avantages de cette méthode sont les suivants :

  • Offre un meilleur modèle pour les contenus à langage neutre ;
  • Pas de synchronisation nécessaire ;
  • Un seul identifiant de nœud ;
  • Fonctionne avec toutes les entités (en somme Drupal) ;

 

 Les inconvénients de cette méthode sont les suivants :

  • Ne fonctionne pas avec les fonctionnalités natives telles que la recherche ou les révisions ;
  • N’est pas compatible avec  les options des nœuds ou la sélection multilingue de i18n ;
  • Les propriétés ne peuvent être traduite (entrée de menu, …etc.) ;

 

Mon avis

 

Le multilingue sous Drupal n’est pas une notion complexe à appréhender mais reste déroutant pour certain. Comme vu dans ce guide, la difficulté réside plus dans la détermination des besoins que dans la mise en place de la solution. Reste, pour ma part, une préférence certaine pour le type de traduction field-level, plus flexible, plus simple à maintenir et plus accessible dans le cadre de développements spécifiques.

Une bonne nouvelle en conclusion de ce guide : le système de multilingue sera complètement refondu avec l’arrivée de Drupal 8 !