Posts tagged ‘php’

J’ai lu pas mal d’articles sur comment créer un cluster de session en PHP, afin de pouvoir utiliser plusieurs serveurs web en front tout en conservant les sessions entres les différents serveurs. Finalement, je vais expliquer la solution de repcached.

Memcached

Memcached est un serveur qui sert à enregistrer et redélivrer des valeurs diverses et variées directement dans la RAM d’un ordinateur.

Avantages : la rapidité d’éxecution des commandes et le support dans PHP en installant une simple extension PECL.
Inconvénient : perte des données en cas de reboot

Dans notre cas, pour stocker des sessions, c’est parfait : un accès rapide à des données, et plusieurs serveurs peuvent accéder à cette base de donnée en même temps.

Repcached

Repcached permet de pallier l’inconvénient de memcached : il s’agit simplement d’un patch qui permet de gérer la réplication entre deux serveurs. En effet, toute commande d’écriture sur un serveur est directement reportée sur l’autre serveur. Ainsi, si l’un des deux tombe, l’autre est à jour et peut prendre le relai. De plus, lors du reboot, toutes les données seront automatiquement récupérées auprès du premier serveur.

Cette solution permet du coup de gérer la redondance de l’information.

Puis-je mettre plus de 2 serveurs ?
Certainement, mais je ne sais pas trop comment… On pourrait mettre 3 serveurs en cycle, mais si l’un tombe, la chaîne est rompue. Il faudrait automatiquement adapter le routage des paquets non plus vers le serveur qui est tombé, mais vers le serveur survivant (en redirigeant les paquets par iptables par exemple).

Installation sous Gentoo

J’ai mis à disposition le serveur memcached 1.2.8 avec repcached 2.2 en ebuild à disposition ici :
http://cyril.me/ebuild/net-misc/memcached/

Cet ebuild se base sur la version 2.1-1.2.6 disponible dans l’overlay wolf32o1.

Match et non-match…

En cette période de coupe du monde de football 2010, quoi de plus naturel que de parler de match ? … Hum.

Problématique

Mon problème aujourd’hui, c’est de sélectionner les listes qui contiennent une certaines expression régulière, mais pas une autre. Plus exactement, et pour faire dans les anglicismes, je cherche « foo.* », mais pas « foobar ».

La solution

Il faut utiliser la forme suivante : (?!regexp) pour choisir quelque chose qui ne match pas la regexp en question.

Mon exemple en pratique :

$ echo -e 'foo\nfoobar\nfoofighting' | grep -P 'foo(?!bar)'
foo
foofighting

Plus d’informations disponible avec perldoc perlre, en particulier le chapitre sur les expressions régulières étendues (Extended Patterns)

Problème

Lorsque l’on parse des fichiers, surtout les fichiers HTML, on a parfois besoin d’extraire un texte compris entre deux balises. Voici donc un moyen d’y parvenir avec les expressions régulières.

Considérations techniques

Je parlerais ici des expressions régulières perl (et par extension : grep -P et preg_* de php).

Par défaut, un /.*/ ou toute autre expression sera « gourmand » : ça matche tant que ça peut encore matcher. Par exemple, /a*/ appliqué à la chaîne "aaa" va matcher "aaa", et non pas "".

Dans mon cas pratique, j’ai une balise <td id="identifier"> et j’en cherche le contenu. Donc si la regexp utilisée est /<td id="identifier">(.*)<\/td>/ alors je vais matcher ce qu’il y a entre mon td ouvrant, et le dernier td fermant.

La solution

La solution consiste à dire au moteur d’expression régulière de prendre le moins possible, et ça se code comme suit : /<td id="identifier">(.*?)<\/td>/.

Bibliographie : http://social.msdn.microsoft.com/Forums/en-US/regexp/thread/ab975ba5-31dd-4e6d-b72f-5cd6bf374b02 (et oui, parfois on trouve des choses utiles sur les forums de microsoft).

Les arrondis peuvent parfois réserver des surprises. Regardez par exemple le code suivant :

  1. <?php
  2. for ($i = 0; $i <= 1; $i += 0.05)
  3. {
  4.   printf ("%.2f %.1f %.1f\n", $i, $i, round($i, 1));
  5. }
  6. ?>

Ce qui nous donne :

0.00 0.0 0.0
0.05 0.1 0.1
0.10 0.1 0.1
0.15 0.2 0.2
0.20 0.2 0.2
0.25 0.2 0.3
0.30 0.3 0.3
0.35 0.3 0.4
0.40 0.4 0.4
0.45 0.4 0.5
0.50 0.5 0.5
0.55 0.5 0.6
0.60 0.6 0.6
0.65 0.7 0.7
0.70 0.7 0.7
0.75 0.8 0.8
0.80 0.8 0.8
0.85 0.9 0.9
0.90 0.9 0.9
0.95 1.0 1.0

Les deux résultats sont différents !

L’explication, vous la trouverez dans la documentation de perl (perldoc -q round) :

Don’t blame Perl.  It’s the same as in C.  IEEE says we have to do this.  Perl numbers whose absolute values are integers under 2**31 (on 32 bit machines) will work pretty much like mathematical integers.  Other numbers are not guaranteed.