fév 23

Alors me voila de retour sur Paris, après une semaine de mauvais temps dans un pays où la dernière fois où il a plu devait être en 1912… Du coup, je me remet en jambes avec quelques news du milieu Magento :

Sortie de la 1.4 CE

Bon, finalement c’est fait, la 1.4 de Magento est sortie. Vous pouvez la trouver ici et un compte rendu complet des nouveautés ici sur Fragento.

Donc après plusieurs mois d’absence, on va enfin pouvoir tester la bête en terme de performances et de sécurité. Je suis en tout cas rassuré que Varien n’ait pas mis de coté la CE plus longtemps car cela devenait politiquement problématique.

Bargento en régions = Apérogento ?

Gabriel et moi travaillons étroitement avec SeL et Varien à l’animation de la communauté Magento en France mais nous n’avons pas le temps de tout suivre ou de tout faire. J’ai appris avec surprise et joie que de nombreux évènements s’organisaient en région, des apérogentos notamment et je trouve cela super.

Vu de Paris, on ne peut pas beaucoup aider à cela me disais-je mais finalement j’ai revu mon jugement. Déjà, apéro ou autres horaires, on peut éventuellement passer faire un bonjour, ca nous fera plaisir, même si ca n’aide en rien les organisateurs :)

Par contre, on peut fournir un peu de logistique aux organisateurs ! De la visibilité en annonçant ca sur Wikigento, Bargento (et probablement Fragento même si je n’en ai pas encore parlé à Gabriel) voir même en faisant poster par Varien un billet avec un espèce d’agenda sur le blog FR.

Ensuite, j’ai des bases de données  assez complète de la sphère Magento en France, ca pourrait permettre de faire un petit mailing pour les organisateurs pour pousser la chose.

Bref, si vous voulez faire un Apérogento en région, comme à Lille, Toulouse et Lyon où on m’en a déjà parlé, je suis tout à fait prêt à donner un coup de main mailing et de la visibilité pour les organisateurs ! Il suffit de me contacter : philippe[at]wikigento.com

Des plugins sympas pour Magento

Déjà Cocorico, un plugin Français pour commencer. La communauté est active, les idées fusent et les modules émergent. La société Xhéos m’informe, par l’entremise de Michaël Thieulin, que l’extension AMF service permet une intégration complète de modules Air/Flex dans le core de Magento.

Le protocole AMF s’invite donc dans le core de Magento et permet également des traitements de plus grands volumes de manière plus efficace. Faire communiquer du Flash sur le front office avec votre Backoffice, c’est partit avec AMF Webservice.

Dans la série on s’y intéresse : les plugins de performances.

L’incontournable Fooman Speedster qui concatènent les JS et les CSS pour réduire leur taille et optimiser le transfert n’est plus seul en piste puisqu’en ce moment plusieurs initiatives visent à optimiser les transferts, les requêtes, les compilations. Où se situe l’avenir ?

Dans mon idée, vous le savez, sur la compilation du PHP.

Un langage interprété ne sera jamais aussi rapide qu’un compilé. En attendant que les initiatives en ce sens (dont une très prometteuse dont je vous reparlerai) voient le jour, des plugins visent à améliorer les temps de chargement.

Bien que je n’ai pas eu encore l’occasion de les essayer, Delorum propose des Magento lignthing hyper megaspeed modules (je vais essayer de benchmarker cela). J’ai vu une autre société proposant des modules similaires à la vente mais l’URL ne me revient pas (EDIT : ah si en fait c’est ici, magento Booster). Si  vous en avez, postez en commentaire, on fera un petit benchmark pour voir qui donne quoi !

Dans les facteurs externes pouvant améliorer les performances de la bête (qui ne cesse de progresser dans son core, reconnaissons le) le moteur de recherche SolR de l’apache consortium vous donnera des recherches de la plus grande rapidité, même dans des catalogues énormes comme dans le c as du Furet du Nord (réalisé par Smile, hébergé et optimisé par NBS System). Toujours dans les “externes” (même si Zend a un unified installer avec Magento), Zend Server améliore les performances avec son Full Page Cache et ses différents mécanismes.

La vitesse comme facteur de ranking Google

Matt Cutts de Google a expliqué en novembre dernier que Google avait une forte pression interne en ce moment, notamment de l’un de ses fondateurs, pour intégrer la vitesse de chargement d’une page comme facteur de ranking.

C’est l’avènement d’une chose que l’on suspectait tous et Google l’officialise quelque part en laissant l’info filtrer publiquement. Le plus étonnant en fait c’est que ce facteur était déjà probablement pris en compte depuis des mois d’après nos tests, sans que Google ne le dise.

La question qui subiste est donc de savoir si pour posséder un bon référencement naturel il faut avoir une page qui se charge vite ou une page qui se charge plus vite que les autres. La deuxième option me parait un peu radicale par contre il y a fort à parier que les sites lents à charger se verront sanctionner dans le référencement naturel puisque, dixit un fondateur du géant, “passer de la recherche au site doit se faire aussi naturellement que tourner une page d’un livre”.

Un Bargento International

Ok on y est, on passe au dessus du gouffre et on verra bien comment ca va se passer… Bargento devient international. En gros, on invite nos copains européens qui n’ont pas la chance d’avoir un évènement local à Paris pour venir échanger avec nous tous.

La décision a été complexe à prendre, le cafouillage de dates vient en partie de là mais Bargento va en ressortir plus grand, plus fort et plus beau. Avec des fournisseurs de solutions et de compétences de tous horizons, des plugins que vous ne soupçonniez même pas, des clients des quatre coins de l’Europe !

Venez donc faire la fête internationale avec nous le 28 mai 2010, plus d’info prochainement sur Bargento.fr

VN:F [1.8.4_1055]
Rating: 6.0/10 (1 vote cast)
Partager cet article :
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Slashdot
  • Wikio FR
  • email
  • LinkedIn
  • Live
  • MySpace
  • Technorati
  • blogmarks
  • Print
  • RSS
  • Twitter
  • viadeo FR
  • Wikio

écrit par Philippe Humeau

déc 20

Javascript et PHP sont-ils des sources de ralentissements ?


Je vais me faire des amis avec un titre comme celui-là :)

Maintenant, au-delà de la provoque, menons une analyse objective.

Nous avons, de nos jours, (au moins) deux gros goulots d’étranglement lorsque nous nous adressons à un site Web :

  • Javascript du coté du client
  • PHP du coté du serveur.

Analyse…

Parlons de Javascript…

En général, je m’intéresse plus aux performances des serveurs que des clients au sens “navigateurs”. En réalité, la performance des clients est en générale très liée à celle des serveurs pour être plus précis. Mais le serveur ne peux pas toujours tout.

Notamment les browsers encaissent plus ou moins bien le Javascript et surtout beaucoup de Javascript.

Opera, Chrome, Firefox, Internet Explorer et leurs copains ont une tendance très nette à réagir différemment (je n’apprends rien aux développeurs Web) et surtout à réagir plus ou moins bien et plus ou moins vite en interprétation de Javascript. De plus, ces différences se cumulent avec des comportements très différents d’un browser à l’autre, notamment le nombre de requêtes concurrentes (nombres d’éléments de la page chargé en parallèle).

Tous les sites récents utilisent énormément de Javascript et ont donc une belle tendance à charger la mule, surtout quand on a plusieurs onglets d’ouverts sur plusieurs sites, on a tout de suite des machine virtuelle javascript au sein des navigateurs qui se mettent à grossir.

Ok, so what ? Qu’est ce que j’y peux me réponde les développeurs…

Eh bien beaucoup de choses en fait. Déjà, un framework c’est bien mais ca n’empêche pas de réfléchir. Faire confiance aveuglément sans regarder le dessous des cartes, c’est ce qui mène au gâchis de ressources.

Optimiser ces points (comme d’autres), c’est ce que j’appelle la “culture atari / amiga”. En gros, à l’époque, les développeurs avaient des machines identiques, des machines avec des limites et on pensait à tirer le meilleur partie du Hardware, on optimisait son programme à la goutte prêt, on passait au plus proche du matériel pour faire des choses que les concepteurs de ces machines n’avaient même pas imaginé.

De nos jours, on prend un framework, on instancie un objet et hop, derrière ca pédale mais c’est plus mon problème… Revenons à Javascript.

Des soucis de tableaux !

Il y a de nombreuses sources de maux dans Javascript, langage qui devient incontournable sur le Web depuis 5 ans. Mais lorsque les sites traitent de sujets plus complexes ou offres de nouveaux raffinement, ce qui était “une brique parmi d’autres” devient plus sensible.

Commençons par un soucis simple de Javascript : les tableaux.

Allouer un tableau en JS déclenche des mécanismes très différents d’un malloc en C. Allons y ! Sous IE, la logique de traitement est la suivante :

var my_array = new Array();

for (i = 0; i < 100000; i ++)

my_array[i] = i;

1°) Je crée un objet array qui est une table de hashage.

2°) Comme une table de hashage est un objet générique, je lui crée un attribue length (taille) et on le met à 0

3°) La boucle fait, pour chaque valeur de i

  • Une conversion de i en string (chaine de caractère, en gros i= « i »)
  • Ajoute un clef de hash pour chaque couple « chaine i », i
  • Réajuste la valeur de length

OMG. Donc, rien que pour assigner une valeur au tableau, on a fait 3 opérations (dont deux totalement inutile si on a codé un jour en C).

Pour compléter le tableau, les allocations réelles de mémoire ne sont pas continues car les tableaux sont gérés sous la forme de « sparse » array.

C’est avantageux en terme d’usage réel de la RAM car les blocks vides ne sont pas alloués, par contre les allocations ne sont pas contigüe. Du coup, les accès à ces blocks de données ne se font pas à la suite et n’utilise pas certains mécanismes de prédiction des processeurs ou certains caches des OS. De plus les entrées du tableau ne sont pas indexées.

Bon, maintenant, on a tout pour faire une usine à gaz de compétition !

Pour résoudre ce premier point, sous IE 8, le « sparse array » est détecté comme étant dense ou non. En gros il est très peuplé ou non. Pour que l’heuristique de IE8 comprenne que c’est un « dense sparse array », il faut que ce tableau soit d’une taille explicite (en théorie mais un autre blog ne dénote pas de différence de perfs sur ce point) par contre, il faut en initialiser tous les éléments. Le défaut c’est que toute la RAM est allouée et le coté « sparse » disparait.

Sur un gros PC ce n’est pas si dramatique mais sur un téléphone portable, ouch… Du coup, initialiser l’ensemble du tableau n’est pas toujours la bonne option. Un comportement optimal serait de détecter le navigateur et de lui proposer un Javascript optimisé pour le ratio Rapidité, consommation de CPU & RAM, logique de traitement. Une sorte de librairie optimisée de gestion des tableaux, dépendante de la plateforme qui l’exécute.

En termes d’impacts c’est non négligeable !

Quelques très bon liens pour ceux que ca intéresse. Le premier blog a d’ailleurs de très bons papiers d’une manière générale !

http://www.outofwhatbox.com/blog/2009/11/javascript-array-performance-initialize-to-optimize/

http://www.outofwhatbox.com/blog/2009/12/javascript-array-performance-and-why-it-matters/

http://blogs.msdn.com/jscript/archive/2008/03/25/performance-optimization-of-arrays-part-i.aspx

PHP et les performances : plantons le décor


Revenons à nos serveurs ! Dans une infrastructure Magento, ce qui pompe dur au niveau des performances, c’est PHP et de très loin.

Il faut évidemment de la RAM pour accélérer les accès et traiter les données mais les appels PHP coutent très chers. Et c’est bien logique car le Web est coincé dans un incroyable paradoxe.

Les langages interprétés (comme PHP) sont très adaptés à certains traitements mais d’une manière générale, pour tous les traitements répétitifs ou massifs, on les évite.

L’idée c’est que dans la rapidité des langages, l’échelle est très claire :

Les compilés :

Les langages ASM/C et C++ sont compilés et (donc) très rapides. On décrit le code et cela se transforme en Opcode directement interprétables et optimisables par le processeur. Tous les caches deviennent super efficaces (L1/L2/L3 du processeur notamment) et le programme traite les données au fil de l’eau et au fil du temps. Le programme se charge en mémoire, il ne s’arrête que quand on lui demande et peut sommeiller le temps d’attendre son prochain traitement.

Assembleur : niveau processeur directement, très peu voir pas d’interprétation, vitesse maximale.

C : Le code produit par un compilateur C est très proche de l’assembleur et donc extrêmement rapide. Pour autant cela reste un langage relativement évolué, contrairement à l’assembleur on a pas à tout écrire de zéro, des librairies existent, des includes, du code un peu évolué d’une manière générale.

C++ : Un langage C évolué et Objet. On monte encore un peu dans les couches, on fait de l’objet et du fonctionnel, on en est plus à la douce barbarie redoutablement efficace de l’assembleur mais ca reste un code qui, une fois compilé, est redoutablement efficace.

Très peu souples en typage ou en gestion de la mémoire, ces trois langages compilés, pour ne citer qu’eux, sont extrêmement rapides !

La machines virtuelles :

Ce sont des programmes qui crée un environnement permettant d’exécuter d’autres programmes en leur sein. L’intérêt essentiel est de s’affranchir de la couche en dessous, en gros le programme devient portable partout. Si la VM existe pour l’environnement matériel cible, le programme tournera (presque) à l’identique sans rien redévelopper. L’inconvénient, comme toute forme de virtualisation, c’est que la VM consomme de la ressource pour créer cette couche d’abstraction, bilan ces langages ne sont pas toujours des foudres de guerre.

Java et autres JVM

Java est le plus connu des langages tournant dans une machine virtuelle, la JVM. C’est un bon langage, objet, évolué et indépendant du matériel mais il souffre de devoir être compilé tout en étant pas aussi rapide qu’un autre langage compilé.

Les « interprétés » :

Aïe. Perl, PHP et de nombreux copains à eux sont des langages dits « interprétés ». A chaque fois qu’il est lancé, le programme (test.php par exemple) est lu par un interpréteur externe (php par exemple), le fichier est parcouru, compilé à la volée quelque part, mais une fois finit, on repart de zéro. Le fichier programme à interpréter est donc lu à chaque fois et le programme qui le lit, l’interpréteur, est un programme qui est lui chargé à chaque exécution aussi.

PHP :

Un des plus célèbres. Zend au dessus est en fait composé de PHP objet évolué au sein d’un Framework, encore une couche d’abstraction. Donc si l’on compare avec nos précédents amis, Zend c’est le C++, Php le C sauf que tout cela est lu/chargé/parsé/interprété puis exécuté en continu. C’est un peu comme si on avait à se taper la compilation a chaque fois qu’on lance le programme… En fait l’image est très exacte puisque c’est quasiment exactement ce qui se passe. Bilan, les langages interprété c’est pratique, facile à maintenir et programmer, on s’affranchit de tous les aspects un peu rigoureux d’allocation mémoire ou de gestion des taches de bases mais le coût en terme de performances est énorme.

PS : Javascript est un langage de scripting interprété tournant dans une machine virtuelle (navigateur)… Tout pour gagner J

Vers un PHP compilé ?


Comme signalé plus haut, l’interprété c’est consommateur et pas adapté aux traitements récurrents. Maintenant si l’on considère une architecture d’hébergement Web, que se passe-t-il.

Admettons que le site soit en Magento, on a un framework de deuxième niveau, qui repose sur un framework de premier niveau (Zend) qui repose sur un langage interprété objet (PHP5) qui repose sur un interpréteur (Php) qui lui-même est compilé et s’adresse en assembleur au processeur.

Ajoutez un peu de virtualisation là-dessus et avant qu’une requête ne passe à travers tout ce maillage, vous avez perdu une quantité de puissance tout proprement hallucinante !

En soit, aucun reproche au fait d’utiliser PHP ou sa syntaxe, par contre, soyons clairs l’approche est juste complètement aberrante. En fait si on essayait de faire pire, le seul moyen, ca serait de faire tourner l’interpréteur php dans une JVM…

Et oui, ce n’est pas anodin mais bien dramatique. A chaque fichier PHP que vous chargez, l’interpréteur est lancé. A chaque fichier php de chargez, vous provoquez toute la cascade de compilation, d’accès disque, d’exécution. Quand un visiteur passe, il provoque donc des centaines de lancement du programme PHP qui va interpréter autant de fichiers… C’est une boucherie, une hémorragie de puissance pour finalement un problème très bête.

Le problème ce n’est pas Magento, Zend ou les fichiers PHP en soit. Sortons de la barbarie de l’assembleur, vive l’objet et tout et tout, on développe plus vite, on réutilise du code, on capitalise des librairies ! C’est l’avancement logique, l’avenir, donc ca va continuer à se développer. Par contre, pourquoi on ne compile pas tout cela ?

La charge CPU des serveurs serait juste divisée par un facteur 10 à vue de nez… C’est à ce point négligeable ? Plus clairement, sur un serveur, au lieu d’accueillir 20 000 personnes par jours par exemple, on en accueillerait 200 000. Avec le même serveur. L’approximation est un peu grossière mais pas outrancière non plus.

Le Web, qui par essence provoque des milliers de lecture et interprétation de fichier de programme, utilise un système d’interprétation, ce qui est la pire façon de faire, ce qui est le plus consommateur possible. Voici le paradoxe.

Si je me la faisais à la Yann Arthus-Bertrand, je redirais « alors pourquoi toi, homo sapiens sapiens, ne compile tu pas tes langages Web ?». Es-tu conscient des ressources gâchées par cette hérésie et de l’impact, de l’empreinte carbone, de cette approche incompréhensible ? Tu veux vraiment défoncer les puits de soleil ? Tu es un inconscient pathologique, un criminel notoire, un serial-gâcheur ? Ooops, je m’emporte… Yann (dont j’aime beaucoup le travail mais un peu moins la voix monocorde) n’irait pas jusque là !

« Pourquoi ne compile t’on pas ? », bon ok, j’arrête de faire mon YAB…

Je n’ai rien contre les développeurs, qui n’y peuvent pas grand-chose si ce n’est optimiser leur code (ca serait déjà un bon début pour certain ceci étant). Ce qui me froisse par contre, c’est que l’on a pas encore de solutions parfaitement mûres pour corriger ce point.

Des soucis assez complexes de conception sont au rendez-vous pour passer du PHP de l’état interprétable à l’état compilé. Mais ne vous y trompez pas, le Graal est au bout de la route.

Plusieurs initiatives sont en cour de développement par des gens talentueux que je ne peux qu’encourager dans cette voie : Roadsend et PHC (Php compiler mais qui paraît à l’arrêt) semblent être les leaders dans cette voie.

http://www.phpcompiler.org/

http://www.roadsend.com/home/index.php?pageID=compiler

L’autre approche possible serait un cache plus efficace, pas uniquement des opcodes comme APC mais bien des pages rendues, du résultat de l’interprétation PHP. C’est ce vers quoi se dirige Zend Server, c’est une bonne première transition mais le compilateur serait bien LA solution !

En conclusion


Je dirais que PHP et surtout le modèle interprété qui va avec et Javascript et surtout l’implémentation qui en ait faite des les navigateurs autant que dans le code de certaines pages Web, sont deux problèmes.

Ces deux axes de progression nous apporteraient un Web plus rapide, souple et agréable d’utilisation. Le réseau n’est plus réellement une limite, les processeurs sont suffisamment puissants alors deux cas sont possibles :

- Quelques personnes douées arrivent au bout de ces deux problèmes

- Tout le monde se contente de ce qu’on a, on enterre la logique d’optimisation de l’époque atari & amiga, on tue les phoques et la banquise en consommant inutilement des ressources informatiques précieuses. On compense par plus de puissance, plus de ressources consommées, plutôt que de mieux utiliser.

Un classique me direz-vous ?

VN:F [1.8.4_1055]
Rating: 5.7/10 (12 votes cast)
Partager cet article :
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Slashdot
  • Wikio FR
  • email
  • LinkedIn
  • Live
  • MySpace
  • Technorati
  • blogmarks
  • Print
  • RSS
  • Twitter
  • viadeo FR
  • Wikio

écrit par Philippe Humeau \\ tags: , , , , , ,

juil 01

Bonjour à toutes et à tous,

Ce coup-ci l’article sera en anglais car c’est une publication d’un white paper rédigé à l’origine par NBS System sur les performances de Magento quand on y couple Zend server. Les tests & benchmarks sont fait entre les versions 1.2, 1.3 et 1.3 avec le flat catalog d’activé puis avec Zend Server et enfin avec Zend server incluant le page cache (version payante).

Ce white paper est en licence Creative commons paternity no commercial use, vous pouvez donc le télécharger, le modifier, le diffuser à votre convenance, sauf pour usage commercial. Celui-ci est uniquement autorisé aux sociétés NBS System, Zend et Varien. (NBS System peut autoriser explicitement l’usage commercial de ce contenu sur demande)

Vous pouvez le télécharger dans sa version PDF intégrale ici.

cc-logo

Magento & Zend Benchmarks

Version 1.2, 1.3 (with & without Flat Catalogs)

1. Foreword

Magento is a PHP/Zend application which intensively uses the CPU. Since version 1.1.6, each new version includes some mechanisms aimed to improve the performances. The goal is to use fewer resources for a given e-shop, which mainly means less CPU, in order to host more users with the same hardware.

One key to achieve better performances is how to optimize PHP pages generation and service. “LAMP” servers are well known and usually run Apache server with mod-php, eventually in fast_cgi mod.

Zend, the PHP Company, made a specific server (Zend Server), which includes a web application stack that (among other things) improves application performances through page caching and opcode reorganization & acceleration.

Apache and Zend Server is an alternative to the usual Apache and mod-php to run Magento, the goal of theses studies & tests is to qualify and estimate the performances added by the use of this software.

Many thanks to Yoav Kutner (Varien’s CTO) for providing us with prefilled catalogs for 1.2 and 1.3 version of Magento. Thanks goes as well to Zend labs for providing help in configuration and tweaking of the Zend Server as well as explaining the in depth mechanism of the solution.

Lire la suite »

VN:F [1.8.4_1055]
Rating: 7.5/10 (2 votes cast)
Partager cet article :
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Slashdot
  • Wikio FR
  • email
  • LinkedIn
  • Live
  • MySpace
  • Technorati
  • blogmarks
  • Print
  • RSS
  • Twitter
  • viadeo FR
  • Wikio

écrit par Philippe Humeau \\ tags: , , , , ,

juin 23

Mage_compiler : une bonne nouvelle à deux titres


Même si les débuts de Mage_compiler sont discrêts, cette nouvelle option est un bon signal de plus :

1°) Varien signe ici un mouvement supplémentaire dans le sens de l’optimisation des performances et depuis la 1.1.6, toutes les versions prennent cette direction. On arrive à un point où le gain cumulé approche les 35 à 70% selon les sites.

Magento est très largement plus fonctionnel et avancé qu’Os commerce, d’où la nécessité d’avoir plus de puissance pour le suivre. Rien de si illogique à cela. En version 1.0.0 on avait un facteur ~6, on en est à un facteur ~2/3. En huit mois, chapeau bas. La bonne nouvelle c’est que l’on gagne en performance, de manière continue et que ce chemin est bien un point majeur pour Varien.

2°) C’est une solution qui va permettre aux serveurs “standards” et aux petites infrastructures de gagner en performance de manière sensible.

Comment ca marche


Vous pouvez l’activer dans le back office en version 1.3.2.1 ou supérieur. Une fois ceci fait, Mage_compiler va en fait concaténer les fichiers liés à Magento en deux librairies et ainsi soulager considérablement les I/O (Input/Output) sur les disques des serveurs.

En effet, l’organisation du code en librairie et en fichiers facilite la maintenance mais complique la vie des machines. Charger un fichier commence par l’ouverture d’un handler, la sequence de lecture, potentiellement la fermeture de ce handler et ceci mutiplié par des centaines voir des milliers de fichiers. Toute économie sur ce point est donc sensible.

Mage_compiler “compile” enfin plus exactement regroupe (merge) ces nombreux fichiers afin de soulager le système de tous ces chargements.

Si l’on a une machine avec peu de mémoire et/ou des disques peu rapides, le gain sera très sensible, peut être jusqu’à 30% voir 40% car les fichiers ne peuvent rester en mémoire avec peu de RAM, il faut donc souvent les charger. Si le disque est lent, cette opération est couteuse.

Si votre infrastructure était déjà doté de serveur avec beaucoup de RAM qui ne décharge pour ainsi dire jamais des fichiers, le gain sera faible, de l’ordre de 5% maximum. De la même façon si vous avez des rolls de disques durs en 15 000 tours / minutes en SAS, il y a peu de chance que votre gain dépasse les 10%, même avec peu de RAM.

Les grands gagnants de cette version seront donc les serveurs bas ou moyen de gamme, soit dotés de peu de RAM (moins de 2 Go) soit dotés de disques lents (SATA en 7200 T/m) voir les deux.

J’espère avoir le temps prochainement de vous proposer des valeurs plus concrêtes en termes de gain de performances, après quelques benchs.

VN:F [1.8.4_1055]
Rating: 0.0/10 (0 votes cast)
Partager cet article :
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Slashdot
  • Wikio FR
  • email
  • LinkedIn
  • Live
  • MySpace
  • Technorati
  • blogmarks
  • Print
  • RSS
  • Twitter
  • viadeo FR
  • Wikio

écrit par Philippe Humeau \\ tags: , , ,

mai 22

Introduction


Cet article est le premier d’une série de 3 sur la configuration d’un infrastructure Magento complète, comprenant pour l’exemple un serveur qui sera Firewall/Reverse proxy/Load Balancer, deux autres qui seront des Serveur Web frontaux et un quatrième qui sera en charge de la base de données.

Plan des posts

1/3 : Configuration du firewall, du load balancer et du Rproxy
2/3 : Configuration des serveurs Web (APC / Apache / PHP)
3/3 : Configuration de la base de données (Mysql)

Le setup de l’infrastructure Magento

archi de baseInternet, routeurs et hop, on tombe sur quoi ?

Le Firewall, reverse proxy, load balancer.

Le premier élément réellement intelligent et puissant sur lequel on va pouvoir travailler, le premier serveur quoi. Parfois l’élément Firewall est séparé et repose sur une appliance en amont mais dans le principe, si vous faites dans le full opensource, vous aimez netfilter et donc le firewall de Linux.

C’est par ailleurs un excellent Firewall, je vais donc l’intégrer à ce petit tuto et même démarrer par là !

Pour cet exemple et le paramétrage des fichiers de configuration, le firewall/RP/LB est en 192.168.1.1, les serveurs Web sont en 192.168.1.2 et .3 et la DB est en 192.168.1.4 et le magasin “virtuel” s’appel www.demostore.fr.

Enfin, cote ip publique, j’ai utilisé 33.44.55.66 comme étant celle de demostore.fr et 88.77.111.222 comme étant celle des admins. Vous trouverez ces paramètres dans les fichiers de configuration du firewall, du reverse proxy et du load balancer, il faudra les modifier pour vos besoins.




Points non couverts dans ces 3 articles

Je vais me la jouer un peu à la Ruquier, donc ce soir, on ne recevra pas, euh pardon, dans cette série de 3 articles, on ne verra pas :

  • Comment faire de la redondance mutli datacenter avec BGP et les synchros de sites & de DB
  • Comment séparer les flux de bases de données en écriture & lecture sur deux DB
  • Comment faire du Master/Master Master/Slave ou du Cluster en Mysql
  • Comment isoler le backoffice en terme de performances sur les serveurs frontaux
  • Comment isoler le backoffice en terme d’accès aux bases de données

On ne verra pas tout cela car :
D’une part parce que cela serait très long et très complexe à expliquer et que les compétences nécessaires pour faire le tour du sujet sont très vastes. D’autre part parce que ca va déjà faire un bon volume à rédiger et donc que ca va prendre du temps. Et enfin parce que ces points sont très critiques sur le terrain commercial et qu’ils sont actuellement des avantages en faveur de ma société vis à vis de ses concurrents.

Vu que la concurrence dans le milieu de l’infogérance Magento est assez active, ma société NBS System ne peux pas se permettre de révéler ses tous derniers tricks ou ses toutes dernières optimisations pour l’infogérance ou l’hébergemnt de Magento, mais ce qui sera décrit dans les 5 articles correspond à ce que nous utilisions fin décembre 2008, donc des configurations tout à fait décentes et efficaces.

En plus mes collègues bossent en ce moment même avec Zend pour faire un papier très complet sur les performances et l’optimisation avec ZAS (Zend Application Server), je ne vais donc pas dévoiler de secrets avant la publication officielle au Bargento 2.

Préambule sur GRSEC/PAX

Autre point, c’est peu décrit dans cet article mais plus dans un autre dont je donne le lien et aussi sur le net : GRSEC + PAX c’est l’assurance vie de vos serveurs. Ce n’est pas une option : c’est un pré-requis. Grsec/Pax impose de recompiler le kernel, tache un peu complexe quand on a pas l’habitude mais le couple vous protège à 99,999% contre tous les overflow, les off by one et autres cochonneries de ce genre. Que ce soit apache, mysql, php, squid, memcached, apc etc… tous ces applicatifs peuvent avoir un jour une faille de sécurité. Grsec c’est l’assurance que même si ca se produit (et ca se produira), vos serveurs ne seront pas compromis.

Le Firewall


Configuration simple

J’ai réalisé, il y a (très) longtemps de cela, un petit tutoriel pour prendre Iptables & Netfilter en main. Il est incomplet, très vieux, contient des erreurs ou des abbérations que je n’ai pas eu le temps de corriger dans les scripts mais les explications et schémas sont corrects. Vous remarquerez au passage ma maîtrise considérable dans la création de page Web, celle-ci à faillit avoir de nombreuses récompenses pour l’utilisation audacieuse des CSS, mais finalement le jury a préféré un autre site (curieusement).

Ceci étant, ce que l’on souhaite faire ici est assez simple :
- Interdire tout par défaut (comme tout firewall décent)
- Authoriser spécifiquement les connexions d’administration depuis nos IP
- Permettre d’accéder directement aux serveurs derrière également depuis nos IP

Attention, il existe de très nombreux tricks à mettre en place pour avoir le top du top, dans le /proc/sys/net/ipv4, afin d’ajouter des règles anti DOS, d’ajuster la stack IP pour la gestion des connexions demi ouvertes, gérer la réduction des timeouts, et puis aussi par des règles pour loger les attaques, ajouter des systèmes de sondes/IDS etc…

C’est un firewall assez basique que je vais exposer ici. Pour de très fortes charges, il faudra également vérifier les capacités de NAT de la machine qui repose sur un système de buckets, lui même calculé en fonction de la RAM de la machine. Il faudra également redonder la machine, etc… (Mais avant que vous en soyez là, vous pourrez largement vous payer les services de personnes qui voient très bien de quoi je parles)

Préparation du Kernel :

  1. On télécharge les patchs de GRSEC ici, ici (et en option le patch pour iptables ici)
  2. On télécharge le kernel qui va avec la version de grsec ici
  3. On détar/dézip les archives et on applique les patchs (bzip2 -d kernel*; tar xvf grsec*;patch -p0 < gr*.patch)
  4. On ajoute deux ou trois tools qui risque de manquer : install libncurses-dev ncurses-dev make gcc paxtest gradm2 chpax
  5. On configure le kernel (make menuconfig), voici l’ultra minimum :
    - Pas de support des modules, tout en statique (ca évite l’insertion de backdoor)
    - networking/networking options/netfilter/ip:netfilter configuration/activer la majorité des options
    - Security options / Grsec: activez tout sauf dans kernel auditing juste les relocations et forks, dans Pax mettez tout.

C’est une config ultra minimaliste. Pour plus d’info de nombreux sites parle de la compilation du noyau, le howto iptables est un peu plus précis aussi mais c’est trop long à expliquer pour avoir une place ici. Après, de nombreuses petites ou grands optimisations peuvent être effectuées au niveau du noyau, les résultats, du coté performances, comme du coté sécurité s’en ressentiront. Disons que si vous avez correctement configuré votre kernel avec pax et grsec, normalement les autres options par défaut sont rarement débiles.

Pour le firewall à proprement parler, on va faire simple dans un premier temps :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/bin/bash
# short, simple, incomplete, not really commented iptables script for Debianed firewalls/rproxy/load balancers by Philippe Humeau (c) 2009 NBS System, lord Rusty forgive me, amen
 
IPTABLES="/sbin/iptables" 
 
case "$1" in
start) 
 
date=`date +'%b %d %k:%M:%S'`
ADMIN_IP="88.77.111.222" # &lt;-------------- Change me !
SERVERS_IP="192.168.1.0/24"
SERVERS_WEB1="192.168.1.2"
SERVERS_WEB2="192.168.1.3"
SERVERS_DB="192.168.1.4"
INET="eth0"
SERVERS="eth1"
 
echo "$date -- Starting Firewall --" &gt;&gt; /var/log/kern.log
 
echo -e "-&gt; \033[40m\033[1;31mSetting Default Policies to DROP \033[0m &lt;-"
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP 
 
echo -e "-&gt; \033[40m\033[1;33mFlushing all rules &amp; tables \033[0m &lt;-"
$IPTABLES -F
$IPTABLES -X
$IPTABLES -Z
$IPTABLES -F INPUT
$IPTABLES -F OUTPUT
$IPTABLES -F FORWARD
$IPTABLES -t nat -F
$IPTABLES -t nat -Z
$IPTABLES -t nat -X
$IPTABLES -N LOG_DROP
$IPTABLES -A LOG_DROP -m limit --limit 6/h --limit-burst 1 -j LOG --log-tcp-options --log-prefix 'Dropped: '
$IPTABLES -A LOG_DROP -j DROP
$IPTABLES -N syn-flood
$IPTABLES -A syn-flood -m limit --limit 10/s --limit-burst 10 -j RETURN
$IPTABLES -A syn-flood -j DROP 
 
echo -e "-&gt; \033[40m\033[1;34m Set kernel networking tweaks \033[0m &lt;-"
echo 0 &gt; /proc/sys/net/ipv4/ip_forward
echo 1 &gt; /proc/sys/net/ipv4/ip_dynaddr
echo 0 &gt; /proc/sys/net/ipv4/conf/all/accept_source_route
echo 0 &gt; /proc/sys/net/ipv4/tcp_timestamps
echo 1 &gt; /proc/sys/net/ipv4/tcp_syncookies
echo 0 &gt; /proc/sys/net/ipv4/conf/all/accept_redirects
echo 2 &gt; /proc/sys/net/ipv4/conf/all/rp_filter
echo 1 &gt; /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
echo 16384 &gt; /proc/sys/net/ipv4/ip_conntrack_max
echo 1 &gt; /proc/sys/net/ipv4/conf/all/log_martians
echo 30 &gt; /proc/sys/net/ipv4/tcp_fin_timeout
echo 2400 &gt; /proc/sys/net/ipv4/tcp_keepalive_time
echo 0 &gt; /proc/sys/kernel/printk
echo 1800 &gt; /proc/sys/net/ipv4/tcp_keepalive_time
echo 0 &gt; /proc/sys/net/ipv4/tcp_window_scaling
echo 0 &gt; /proc/sys/net/ipv4/tcp_sack
echo 64 &gt; /proc/sys/net/ipv4/ip_default_ttl
echo 2048 &gt; /proc/sys/net/ipv4/ip_queue_maxlen
echo 1 &gt; /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
echo 1 &gt; /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo 1 &gt; /proc/sys/net/ipv4/tcp_ecn
 
echo -e "-&gt; \033[40m\033[1;33m INPUT RULING \033[0m &lt;-"
$IPTABLES -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A INPUT -i $INET -s $ADMIN_IP -j ACCEPT
$IPTABLES -A INPUT -i $SERVERS -p tcp --dport 11211 -j ACCEPT # memcached
$IPTABLES -A INPUT -i $SERVERS -s $SERVERS_IP -j ACCEPT        # accept très (trop) générique pour les requêtes des serveurs au rp/lb/fw
$IPTABLES -A INPUT -p ICMP -i SERVERS -s $SERVERS_IP -j ACCEPT
$IPTABLES -A INPUT -p ICMP -i lo -j ACCEPT
$IPTABLES -A INPUT -i $INET -s $SERVERS_IP -m limit --limit 3/m -j LOG_DROP # "Spoofed packet: "
$IPTABLES -A INPUT -f -m limit --limit 3/m --limit-burst 1 -j LOG_DROP # "Frag packet: "
$IPTABLES -A INPUT -i $INET -p icmp -m limit --limit 12/hour --limit-burst 1 -j LOG --log-prefix "ICMP: "
$IPTABLES -A INPUT -p tcp --dport 22 -m state --state NEW -m limit --limit 3/m --limit-burst 2 -j LOG_DROP # "SSH loggin attempt"
$IPTABLES -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -m limit --limit 3/m --limit-burst 5 -j LOG_DROP # "Stealth XMAS scan"
$IPTABLES -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -m limit --limit 3/m --limit-burst 5 -j LOG_DROP --log-prefix "Stealth XMAS-PSH scan"
$IPTABLES -A INPUT -p tcp --tcp-flags ALL ALL -m limit --limit 3/m --limit-burst 5 -j LOG_DROP # "Stealth XMAS-ALL scan"
$IPTABLES -A INPUT -p tcp --tcp-flags ALL FIN -m limit --limit 3/m --limit-burst 5 -j LOG_DROP # "Stealth FIN scan"
$IPTABLES -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -m limit --limit 3/m --limit-burst 5 -j LOG_DROP # "Stealth SYN/RST scan"
$IPTABLES -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 3/m --limit-burst 5 -j LOG_DROP # "Stealth SYN/FIN scan(?)"
$IPTABLES -A INPUT -p tcp --tcp-flags ALL NONE -m limit --limit 3/m --limit-burst 5 -j LOG_DROP # "Stealth Null scan"
$IPTABLES -A INPUT -p tcp --dport 0 -m limit --limit 6/h --limit-burst 1 -j LOG_DROP # "Port 0 OS fingerprint"
$IPTABLES -A INPUT -p udp --dport 0 -m limit --limit 6/h --limit-burst 1 -j LOG_DROP # "UDP port 0 OS fingerprint"
$IPTABLES -A INPUT -p tcp --sport 0 -m limit --limit 6/h --limit-burst 5 -j LOG_DROP # "TCP source port 0"
$IPTABLES -A INPUT -p udp --sport 0 -m limit --limit 6/h --limit-burst 5 -j LOG_DRop # "UDP source port 0"
$IPTABLES -A INPUT -p tcp -m multiport --sports 20,21,22,23,80,110,143,443,993,995 -m limit --limit 6/h --limit-burst 1 -j LOG_DROP # "Napta/smurfing/Drd/Dos"
$IPTABLES -A INPUT -i $INET -p tcp ! --syn -m state --state NEW -j DROP # "drop TCP connexion wich doesn't start by a syn"
$IPTABLES -A INPUT -m state --state INVALID -j DROP
$IPTABLES -A INPUT -i $INET -p tcp --syn -j syn-flood 
 
echo -e "-&gt; \033[40m\033[1;32m FORWARD RULING \033[0m &lt;-"
$IPTABLES -A FORWARD -m state --state INVALID -j DROP
$IPTABLES -A FORWARD -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A FORWARD -i $INET -o $SERVERS --dport 80 -p tcp -m state --state NEW -j ACCEPT
$IPTABLES -A FORWARD -i $INET -o $SERVERS --dport 443 -p tcp -m state --state NEW -j ACCEPT
$IPTABLES -A FORWARD -o $INET -i $SERVERS --dport 20 -p tcp -m state --state NEW -j ACCEPT
$IPTABLES -A FORWARD -o $INET -i $SERVERS --dport 21 -p tcp -m state --state NEW -j ACCEPT
$IPTABLES -A FORWARD -o $INET -i $SERVERS --dport 22 -p tcp -m state --state NEW -j ACCEPT
$IPTABLES -A FORWARD -o $INET -i $SERVERS --dport 25 -p tcp -m state --state NEW -j ACCEPT
$IPTABLES -A FORWARD -o $INET -i $SERVERS --dport 80 -p tcp -m state --state NEW -j ACCEPT
$IPTABLES -A FORWARD -o $INET -i $SERVERS --dport 443 -p tcp -m state --state NEW -j ACCEPT 
 
echo -e "-&gt; \033[40m\033[1;32m OUTPUT RULING \033[0m &lt;-"
$IPTABLES -A OUTPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A OUTPUT -p ICMP -j ACCEPT
$IPTABLES -A OUTPUT -p TCP --dport 20 -j ACCEPT
$IPTABLES -A OUTPUT -p TCP --dport 21 -j ACCEPT
$IPTABLES -A OUTPUT -p TCP --dport 22 -j ACCEPT
$IPTABLES -A OUTPUT -p TCP --dport 25 -j ACCEPT
$IPTABLES -A OUTPUT -p UDP --dport 53 -j ACCEPT
$IPTABLES -A OUTPUT -p TCP --dport 80 -j ACCEPT
$IPTABLES -A OUTPUT -p UDP --dport 123 -j ACCEPT
$IPTABLES -A OUTPUT -p TCP --dport 123 -j ACCEPT
$IPTABLES -A OUTPUT -p TCP --dport 443 -j ACCEPT
 
echo -e "-&gt; \033[40m\033[1;33m Masquerading \033[0m &lt;-"
$IPTABLES -t nat -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
$IPTABLES -t nat -A POSTROUTING -i -o $INET -j MASQUERADE
 
echo -e "-&gt; \033[40m\033[1;32m Firewall Setup complete, activating Forward \033[0m &lt;-"
echo 1 &gt; /proc/sys/net/ipv4/ip_forward 
 
echo -e "------------------------&gt; \033[40m\033[1;32mEOF : End of Firewall \033[0m&lt;-----------------------"
;; 
 
stop)
echo -e "\033[40m\033[1;31m----------------------&gt; Shutting down Firewall ! &lt;----------------------\033[0m"
echo " "
IPTABLES="/sbin/iptables"
$IPTABLES -F
$IPTABLES -X
$IPTABLES -Z
$IPTABLES -F INPUT
$IPTABLES -F OUTPUT
$IPTABLES -F FORWARD
$IPTABLES -t nat -F
$IPTABLES -t nat -Z
$IPTABLES -t nat -X
echo 0 &gt; /proc/sys/net/ipv4/ip_forward
echo "-&gt; DONE ! &lt;-"
;;
 
*)
echo "Usage: /etc/init.d/firewall {start|stop}"
exit 1
;;
 
esac
exit 0


Quelques points :
- N’oubliez pas de durcir tous vos noyaux de serveurs, tout spécialement celui-ci, avec le patch GRSEC pour le kernel Linux. (ca doit aussi être décrit dans le howto de mémoire).

- Si on veut être plus méchant, au lieu de DROP on peut utiliser TARPIT si on a compilé iptables avec, ca fait un bel effet sur la machine attaquante !

- Si le scipt ne charge pas c’est que j’ai fais un faute de frappe quelque part, corrigez là :-) Si il ne charge pas parcequ’il manque des target, ajoutez les dans le noyau au moment de sa compilation.

Le Reverse Proxy


Introduction

Le Firewall est une fonction en soit est très peu consommatrice car, sur un noyau linux, c’est embarqué. Netfilter et son application de pilotage iptables sont des outils très puissants et très économes.

Dans le cas qui nous préoccupe, c’est d’autant plus vrai qu’on va filtrer très peu de chose, ce n’est pas non plus le firewall du pentagone, on va juste protéger les accès d’administration. Sur notre beau serveur, on a dépensé 0,000001% de la capacité CPU, que faire du reste ?

Hummmmm du folding@home, du calcul de Pi, un serveur Quake 3, du Seti project : non !

On va faire un reverse proxy et un load balancer qui eux peuvent commencer à occuper un peu la machine sur ses 99,999999 % de temps CPU restant.

Le reverse proxy, c’est une histoire un peu plus complexe. Si on part sur une solution simple, Squid est très capable. Pour de la dentelle, qui nécessite aussi une optimisation du code pour en tirer le plein partit, Varnish est une solution plus costaud mais réellement plus longue à mettre en place. On va donc ici s’atteler à concevoir un Squid correcte.

Rôle

Le rôle du reverse proxy c’est ca :
rp stats

Réduire les accès aux serveurs Web en les allégeants de tout ce qui n’a pas de valeur ajouté, tout ce qui n’est pas généré. J’ai pris volontairement une page très lourde pour la démonstration.

En l’occurence on va cacher :

  • Le HTML
  • Les CSS
  • Les images
  • Les fichiers Javascript

et forcément, le serveur Web, ca lui fait du bien. En résumé, il se concentre sur les requêtes Ajax et le PHP, il laisse les transferts “de base” au Rproxy. Evidemment, un tour de magie de ce type, ca consomme un maximum en RAM car il faut tout stocker en RAM pour aller vite. Si on doit charger chaque éléments depuis le disque dur, c’est plutôt lent. Un bon reverse proxy a donc beaucoup de RAM et un processeur correct, sans plus puisque la charge processeur est faible.

Au final, même si l’exemple ici, un peu exagéré, montre un gain de 97%, on gagne quand même en général au minimum 75% de trafic en moins vers le ou les serveurs Web. Donc qu’on ait un serveur Web ou plusieurs, le reverse proxy est in-dis-pen-sable.

Une autre optimisation intelligente sur ce point est à faire au niveau du code. Un fichier JS, un fichier CSS et pas des millions, ca change des choses. Du coup, concaténer tout cela intelligemment, c’est un plus non négligeable. Un gars s’est pris la tête à faire le boulot pour vous et encore mieux, il en a fait un plugin Magento, que demande le peuple ? Au fait ca s’appel Fooman speedster module et, depuis l’invention de la fénéantise, c’est un des outils les plus indispensable pour optimiser sans se fatiguer.

Installation de Squid

Vous êtes des gens biens, vous avez une Debian.

Vous pouvez aussi être des gens bien et ne pas avoir de Debian mais dans ce cas vous savez installer une tarball ou un package. Il y a même des gens bien qui travaillent avec OpenBSD par exemple, ils ont toute ma considération mais je ne ferai pas de howto pour ;) (Il n’y a plus de gens bien sous HPUX rassurez moi ?)

Le coté “à la main”, je sais faire aussi mais, personnellement, j’adore APT et DPKG :)

Attention, on se concentre, installer Squid ce n’est pas simple sous debian :

~> su (on passe root car on est jamais loggé en root par défaut)
~> apt-get install squid

Ok on respire, on a fait le plus dur. Un petit café pour se récompenser s’impose, bravo, vous avez bien bossé ! (merci aux gars de Gnu aussi). Ca c’est fait, Squid est installé, on souffle, on respire, c’était dur mais la vie est dure parfois.

Configuration de squid en reverse proxy Magento

Phase 2, on essaye de faire croire aux patrons qu’on est payé à faire quelque chose de balaise et incompréhensible, qui mérite probablement une augmentation énorme mais qu’on va se contenter de 10% et une voiture de fonction : on édite le fichier de configuration.

Bon Squid c’est un proxy et un reverse proxy. En gros ca permet dans un cas comme dans l’autre de gérer un cache pour que les fichiers régulièrement demandés soient dans un cache rapide, mémoire de préférence, plutot que redemandés voir ré interprétés par le serveurs Web. Ca allège énormément les serveurs dans le cas du reverse proxy. Le proxy cache les réponses des serveurs Web aux browsers http pour les acheminer au client sans les redemander. Le reverse proxy lui fait l’inverse (d’où le reverse), il stocke les réponses les plus souvent envoyées par le serveurs aux clients afin de servir ceux-ci sans demander quoique ce soit aux serveurs Web.

Bref Squid c’est complexe, énorme, un fichier de conf de base ca fait dans les 7000 lignes avec les commentaires, je vous livre donc ici une version expurgée des commentaires, juste préparer pour du reverse proxy et dont toutes les fonctions ne sont pas activées, juste les principales. Encore une précision, quand vous utilisez un reverse proxy, n’oubliez pas que votre serveur Web ne verra plus toutes les requêtes… Eh oui, c’est bien le but d’ailleurs. Donc ce qui est intercepté doit être minutieusement loggé pour pouvoir avoir des stats et compléter celles des serveurs Web sous Apache.

Allez, voici la configuration :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# Squid sooooo basic configuration for Magento, by Philippe Humeau &amp; Adrien Urban (c) 2009 NBS System
acl manager proto cache_object
acl localhost src 127.0.0.1/32
acl to_localhost dst 127.0.0.0/8
acl SSL_ports port 443
acl Safe_ports port 80		# http
acl Safe_ports port 443		# https
acl CONNECT method CONNECT
http_access allow manager localhost
http_access deny manager
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
icp_access deny all
htcp_access deny all
 
http_port 192.168.1.1:80 transparent name=proxy_int_IP
http_port 33.44.55.66:80 transparent name=ip_demostore
hierarchy_stoplist cgi-bin ?
 
cache_mem 6144 MB
maximum_object_size_in_memory 8 MB
memory_replacement_policy heap lfuda
cache_dir null /tmp
 
 
access_log /var/log/squid3/access.log squid
access_log /var/log/squid3/access-apache.log combined
refresh_pattern (cgi-bin|\?)	0	0%	0
refresh_pattern .		0	20%	4320
icp_port 3130
 
acl localhost src 127.0.0.1/8
acl localnet src 192.168.1.0/24
 
acl debianUpdate dstdomain ftp.fr.debian.org              # pour les updates Debian
acl debianUpdate dstdomain security.debian.org          # pour les updates Debian
acl dstOutAllowed dstdomain ws.mperf.com                # pour le mailing, remplacer mailperf par votre fournisseur
acl dstOutAllowed dstdomain chart.apis.google.com      # pour les beaux graphs à la google style
acl dstOutAllowed dstdomain www.magentocommerce.com     # devinez
acl dstOutAllowed dstdomain connect.magentocommerce.com # devinez v2.0
acl dstOutAllowed dstdomain pear.php.net                           # devinez v3.0
acl dstOutAllowed dstdomain schemas.xmlsoap.org                # pour les wsdl, soaperie et autres webservices
 
http_access allow localnet debianUpdate
http_access allow localnet dstOutAllowed
 
acl IpInternal myportname proxy_int_IP
acl IpExternal myportname ip_demostore
acl dstdemostore dstdomain www.demostore.fr
acl dstdemostore dstdomain demostore.fr
never_direct allow dstdemostore
 
# demostore
cache_peer 192.168.1.2 parent 80 0 no-query round-robin sourcehash
cache_peer 192.168.1.3 parent 80 0 no-query round-robin sourcehash
cache_peer_access 192.168.1.2 allow dstdemostore
cache_peer_access 192.168.1.3 allow dstdemostore
 
cache_peer_access 192.168.1.2 deny all
cache_peer_access 192.168.1.3 deny all
 
http_access allow dstdemostore
 
http_access deny all
 
access_log /var/log/squid3/demostore-squid.log squid demostore
access_log /var/log/squid3/demostore-apache.log combined demostore

Dans cet exemple, votre serveur dispose de 8 Go de Ram et on en prend 6 pour le cache de squid. C’est évidemment à ajuster en fonction de votre configuration. (cache_mem 6144 MB) On a aussi une taille maximal de fichier à 8 Mo pour cacher les gros objets et on interdit le cache sur disque pour ne pas gréver les performances. On a paramétré le service Squid pour gérer www.demostore.fr et demostore.fr et donné l’accès aux serveurs vers d’autres hosts comme Magento connect ou les updates de Debian.

Le load balancer

Bonne nouvelle : c’est déjà fait !

Eh oui en donnant deux peers vous avez dit à Squid qu’il avait deux serveurs Web dont il devait s’occuper. Vous pourriez vouloir donner un poids différent (ici dans l’exemple c’est du 50/50) si vous avez des serveurs de puissance différentes. Il faudra alors ajouter Weight comme directive dans la déclaration des peers.

Le piège serait de faire du load balancing IP. Netfilter sait le faire, c’est même assez simple à mettre en oeuvre et pour tout vous dire c’est ce qu’on faisait à NBS System avant. Mais cela posait des problèmes quand le client arrivait d’une IP qui changeait en cour de session (gros firewall corporate qui nat par une autre connexion ou même simplement une adsl en ip variable). Du coup il vaut mieux passer par cette solution qui est plus propre.

Memcached


Introduction

Nous y voila, la fin de l’aventure Firewall / Load Balancer / Reverse Proxy est proche…

Si je finis par ce point c’est aussi parce que c’est le plus facile quelque part.

On peut mettre memcached un peu partout dans l’infrastructure, sur le proxy, sur les serveurs Web ou même sur les serveurs de base de données. L’idée c’est de garder les sessions des surfers non pas en fichiers mais en mémoire. D’un point de vue performance, c’est très préférable et c’est simple à réaliser alors pourquoi s’en passer…

Installation

On peut le mettre dans plusieurs endroit ce fameux memcached mais je préconise un serveur qui est unique et accédé / accessible par tous comme la base de données (si on a qu’un serveur de DB) ou le reverse proxy mais, si possible, pas sur les serveurs Web. En effet si l’un tombe, autant que l’autre puisse bosser et reprendre ses sessions. Evidemment, il vaut mieux que le dit serveur soit redondant ou bien costaud pour ne pas tomber sinon c’est toutes les sessions qu’on perd mais vu que le site tombera avec, ca sera un moindre problème :)

Oui, je sais, toujours un peu douleureuse cette phase sous Debian :
~> su (on passe root car on est plus loggé en root, normal)
~> apt-get install memcached php5-memcached

Allez, ca va aller, c’est finit… On respire lentement, le rythme cardiaque redescend !

Configuration

Dans le fichier local.xml de Magento, vous devriez pouvoir ajouter :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<global>
  <cache>
    <backend>memcached</backend>
    <memcached>
      <compression/>
      <cache_dir/>
      <hashed_directory_level/>
      <hashed_directory_umask/>
          <file_name_prefix/>
          <servers>
             <default>
              <host>192.168.1.1</host>
              <port>11211</port>
             <persistent>1</persistent>
           </default>
          </servers>
      </memcached>
  </cache>
<session_save><![CDATA[memcache]]></session_save>
<session_save_path><![CDATA[tcp://192.168.1.1:11211?persistent=1]]></session_save_path>
</global>

On peut aussi mettre memcached en dehors de Magento et de sa configuration, tout simplement en installant le démon avec une configuration dans le /etc/memcached.conf :

1
2
3
4
5
6
7
# memcached ultra simplistic config file by philippe Humeau (c) 2009 NBS System
-d
logfile /var/log/memcached.log
-m 1024
-p 11211 
-u nobody
-l 192.168.1.1


Conclusion


  1. Vous méritez un café après tout ce travail
  2. Je mérite un café après ce travail de rédaction
  3. Il est incompréhensible que les producteurs de café soient pauvres
  4. La personne qui monte un site Magento entièrement dédié au café, il va se faire du blé

Oui… Je sais… J’ai toujours un petit soucis sur les conclusions mais bon, vous commencez à être habitués depuis le temps et puis je me soigne.

Prochain exercice de style, l’article 2/3 : Configuration d’un serveur Web pour Magento !

PS : N’oubliez pas de vous inscrire pour Bargento 2, il reste encore quelques places et après on est complet, ce qui implique que même en arrivant à l’improviste sur place, on ne pourra pas vous faire rentrer pour rester dans les capacités d’accueil de la salle.

De plus, le papier sur Zend Application Server et les performances de Magento devrait apporter un jour nouveau et pas mal de complément sur ce mini tuto / howto.

Par manque de temps, je n’ai pas eu le temps de tout tester sur un serveur donc si il y a des boulettes dans les fichiers de configuration, n’hésitez pas à me les signaler, je modifierai l’article.

VN:F [1.8.4_1055]
Rating: 9.7/10 (3 votes cast)
Partager cet article :
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Slashdot
  • Wikio FR
  • email
  • LinkedIn
  • Live
  • MySpace
  • Technorati
  • blogmarks
  • Print
  • RSS
  • Twitter
  • viadeo FR
  • Wikio

écrit par Philippe Humeau \\ tags: , , , , , , , ,

fév 11

Bonjour à tous,

Ce post va traiter de l’optimisation de l’Opcode APC.
Pour plus d’informations sur APC, ci dessous, un lien de présentation :

http://fr3.php.net/apc

Dans ce document, nous allons aborder quelques points de réglage. Pour ma part, j’estime qu’il procure un gain au niveau du temps d’accès de la page d’accueil de l’ordre de 0,15s (0,40s vs 0,25s), le tuning a amélioré le temps de réponse de 0.05s. En charge, je pense que les réglage on permis d’augmenter la charge sur le serveur avec un facteur 3.

Je n’ai pas de statistiques exactes sur ce point car j’ai modifié 4 tables dans la base Mysql pour optimiser les performances et diminuer les points de blocage.

Les modifications combinées ont permis de diminuer la charge CPU par 10. (avant les modifications, un test de charge de 200 utilisateurs a fait monter la charge CPU à 100. Le même test de charge avec les réglages que je vais présenter et le changement de 4 tables du type MyISAM au type innodb n’a fait monter la charge CPU qu’à 10).

Tout d’abord, je tiens à préciser que je n’ai rien inventé, j’ai effectué quelques recherche et j’ai ensuite testé.

La référence de mon étude se base sur cet article : http://julien-pauli.developpez.com/tutoriels/php/apc/

La première chose que j’ai faite est la mise à disposition de la page apc.php fournie dans le package pecl d’installation. Cette page php permet d’effectuer un diagnostic de l’état d’APC, notamment de savoir comment il est utilisé.

Par défaut, la taille du cache est de 30Mo, ce qui semble suffisant pour la majorité des applications. De mon coté, j’ai estimé qu’il n’était pas suffisant car j’ai la mémoire utilisée à 95%, voir un peu plus et une très forte fragmentation. La fragmentation est un signe qui m’a indiqué que des fichiers sont régulièrement sortis du cache pour en mettre d’autres. L’autre paramètre qui m’a indiqué que des fichiers n’étaient pas cachés est la statistique “hit and misses”, cette statistique etati à 50% de hit. Le simple fait d’augmenter la taille du cache a résolu la fragmentation et mes statistiques de hit & misses sont maintenant proche de 100% de hit (900000 hits vs 300 misses).

J’ai continué mes recherches en parcourant l’article ci dessus et j’ai testé quelques réglages conseillés :
apc.num_files_hint
apc.user_entries_hint
Ci dessous, les réglages spécifiques que j’ai apportés :
apc.shm_size = 128
apc.stat = Off
apc.include_once_override = 1
apc.num_files_hint = 0
apc.user_entries_hint = 0
apc.max_file_size = 2M

Toutes ces fonctions sont détaillés dans la documentation php :
http://fr3.php.net/manual/fr/apc.configuration.php

VN:F [1.8.4_1055]
Rating: 0.0/10 (0 votes cast)
Partager cet article :
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Slashdot
  • Wikio FR
  • email
  • LinkedIn
  • Live
  • MySpace
  • Technorati
  • blogmarks
  • Print
  • RSS
  • Twitter
  • viadeo FR
  • Wikio

écrit par Gilles \\ tags: , , ,

fév 05

Durant nos différents échanges à Bargento, j’ai réévoqué la piste d’un “compilateur de site”.

C’est un projet qui peut prendre de multiples formes, du préloading d’un site pour rendre le cache du reverse proxy efficace immédiatemment ou encore appeler tous les liens avec une spider et sortir un site “Semi statique” à partir du site Dynamique originel.

Plusieurs personnes ont trouvé l’idée intéressantes, certains ont même déjà de l’expérience dans le domaine, un contributeur Drupal, l’admin du vendée Glob (de AFG je crois ?) un monsieur de chez Smile. Je n’ai pas retenu tous les noms ou toutes les bonnes volontées mais je suis prêt à créer un groupe de travail sur ce point avec les volontaires.

L’idée est la suivante :
Les langages interprétés comme PHP ne sont pas très optimisés pour les processeurs et leurs systèmes de cache.
Ce point peut se compenser en imaginant un site Web très dynamique (Zend/Magento par exemple) comme un “code source” de l’époque C++. Le but c’est que la version dynamique reste bien LA référence mais que pour des raisons de performances, ont “pré calcul”, on compile, une partie des pages du site. Du coup, le serveur Web fournit des pages HTML et non plus du PHP qui génère du HTML. Le rapport de puissance peut aller de 1 à 10 sans problème, comprenez qu’un même serveur Web frontal pourrait servir 10000 connexions simultanées au lieu de 1000.

Outre le gain de performances et l’économie de puissance, on constate également que le surfer reçoit une information quasi immédiatemment puisque le serveur n’a plus à générer du HTML puis à l’acheminer mais juste à l’acheminer.

Les limites :
En premier lieu, ceci ne permet d’optimiser que les performances des serveurs Web. En effet, ce qui est allégé, c’est le temps de rendu des pages et uniquement ce point. Rechercher un produit dans une base de données pas optimisée n’ira pas plus vite qu’avant. En poussant le vice, on pourrait précalculer les réponses aux 3 recherches les plus fréquentes dans le moteur selon une espèce de règle des 80/20.

Ensuite, il ne faut pas oublier que le site doit être généré à une fréquence suffisamment élevée pour que les changements importants soient visibles rapidement. Il faut également le “compiler” sur un autre serveur que celui de production car sinon on va entacher ses performances lors de la génération des pages semi-statiques. En fait il faudrait même pouvoir recompiler le site à la demande, sur tout ou partie (les prix uniquement, les articles et les prix, juste une page, comme avec un Makefile en fait)

Les obstacles :
La complexité du projet réside dans le fait que de nombreux élements nécessitent l’affichage d’informations dynamiques. Le caddie d’une personne, ses “choix pour plus tard”, les comparateurs de prix ou de produits etc… De même, interroger la base de données en faisant une recherche sur un site répondra forcément un contenu différent selon la recherche (sinon on risque de décevoir un peu le visiteur).

On ne peut pas non plus trop déporter le processus dynamique sur le poste client, cela peut dans certains cas engendrer des risques de sécurité. La business logic de traitement des commandes et ce genre de choses ne peut pas résider “customer side” dans la machine virtuelle javascript du browser sinon elle est aisée à corrompre.

Mais c’est un peu comme dans la pub pour une certaine carte de crédit :
“Il a ce que vous ne pouvez pas rendre statique, pour tout le reste, précompiler votre site !”

Alors ? Faisable ou pas ? Utile ou juste une idée en l’air ? J’en appel aux volontaires pour qu’on voit si un petit groupe de travail souhaite se pencher efficacement dessus.

VN:F [1.8.4_1055]
Rating: 0.0/10 (0 votes cast)
Partager cet article :
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Slashdot
  • Wikio FR
  • email
  • LinkedIn
  • Live
  • MySpace
  • Technorati
  • blogmarks
  • Print
  • RSS
  • Twitter
  • viadeo FR
  • Wikio

écrit par Philippe Humeau \\ tags: , , ,

jan 11
Nous avions déjà fais nos tests et le Shanghaï d’AMD sortait vainqueur du duel, ce qui nous avait encouragé à équiper notre nouvelle infrastructure d’hébergement Magento entièrement en Shanghaï. Anandthec, très sérieux site se concentrant sur les performances des processeurs, a lui aussi fait des tests de performances, notamment sous Mysql et le résultat est le même, une franche avance pour les nouveaux AMD. De plus, d’après nos essais, ce qui est vrai pour le Mysql l’est également pour les pages générées par le combo PHP/Zend/Magento.
Vous pouvez donc y aller franchement car, en conclusion, on peut dire que “Magento loves Shanghaï” :
perf shanghai/mysql
Le différentiel de performances ne laisse pas l’ombre d’un doute, 27% de requêtes traitées en plus, c’est un résultat écrasant (backend en InnoDB).
Par contre, grosse méfiance, ce qui est vrai pour le hosting LAMP ne l’est pas pour du MS+Oracle ou du calcul pur ou encore de la virtualisation. Attention aussi au fait qu’il faut privilégier les processeurs plus puissants à nombre de coeurs identiques puisque Mysql n’est pas simple à scaler au delà de 4 coeurs.
VN:F [1.8.4_1055]
Rating: 0.0/10 (0 votes cast)
Partager cet article :
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Slashdot
  • Wikio FR
  • email
  • LinkedIn
  • Live
  • MySpace
  • Technorati
  • blogmarks
  • Print
  • RSS
  • Twitter
  • viadeo FR
  • Wikio

écrit par Philippe Humeau \\ tags: , , ,

jan 10

Mais oui, pourquoi au fait ?

Voici une analyse philosophico-technique d’une question existentielle qu’on se pose tous : “Pourquoi Magento est un gouffre de puissance ?”

En premier lieu, Magento dépend d’un autre framework : Zend. Et ce n’est pas le seul à être gourmand, les Ruby on Rail et autres sont aussi des affamés.

Pour revenir à Magento, c’est un framework de deuxième niveau, de l’objet d’objet. Or, revenons aux racines, à l’époque ou Stroustrup, Kernighan et Ritchie nous inventent l’objet et le C++. L’objet c’est une méthode de programmation pensée pour factoriser le code source, faciliter sa réutilisation ainsi que permettre à des humains de manipuler des concepts plus agréables que des (char *), des pointeurs et des librairies à rallonge.

Donc en gros, à partir du C, le C++ a été créé et d’autres langages ont suivi le même processus.

Mais… Car il y a (toujours) un mais, cette structuration objet est plus “lourde”. Simplifier, en général ca veut dire qu’en dessous quelqu’un a fait quelque chose de plus complexe pour vous simplifier la vie. Voyez ca comme un canard, calme en surface mais qui pédale dur en dessous. En objet c’est pareil, la simplicité pour l’humain a impliqué un code plus lourd à digérer pour la machine et puis si on fait des objets c’est bien pour développer des programmes plus utiles, complexes, effiaces etc… La programmation objet a donc une tendance naturelle à compliquer les choses pour la machine mais le compilateur, quand il est performant, réduit tout cela à un assembleur très comparable. Une même fonction en C et en C++ va fournir un code assembleur assez comparable pour que les performances soient proches. Le compilateur est plus complexe, il met plus de temps à compiler, mais l’éxécution du binaire ne sera qu’imperceptiblement plus lente, ce compilateur “gomme” donc la lourdeur engendrée par l’objet.

Résultat : c’est tout bénéfice, l’humain manipule des objets plus agréables et plus utilisables, se lance dans le fonctionnel au lieu d’avoir les mains dans le camboui (ceux qui ont fait du x86 savent de quoi je parle), la machine interprete une fois un peu plus longtemps avec son compilateur et au final, quand le programme se lance, il est aussi rapide !

Oui mais……… PHP n’est pas un langage compilé. C’est un langage interprété. Et la complexité supplémentaire pour la machine qui était gommée par le compilateur ne l’est plus. A chaque interprétation, on reprend le même code, on replonge dans les niveaux d’abstraction objets et on force le CPU a interpréter tout cela. Alors avec juste du PHP “non objet” ca allait encore. Avec du PHP 5, on attaque la notion d’objet, on s’alourdit un peu mais ca tient toujours la route. Avec Zend, c’est déjà nettement plus consommateur de ressources, on est sur une couche d’abstraction supplémentaire et ca comme à se sentir. Lire la suite »

VN:F [1.8.4_1055]
Rating: 10.0/10 (1 vote cast)
Partager cet article :
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Slashdot
  • Wikio FR
  • email
  • LinkedIn
  • Live
  • MySpace
  • Technorati
  • blogmarks
  • Print
  • RSS
  • Twitter
  • viadeo FR
  • Wikio

écrit par Philippe Humeau \\ tags: , ,

déc 12

Comme nous allons parler essentiellement de performances et d’optimisation, il faut que nous convenions d’un vocabulaire commun et d’unité de mesure commune sinon cela va compliquer le dialogue et perturber les comparaisons. Je ne crois pas qu’il y ait réellement de normes en vigueur alors nous avons choisis, à plusieurs, d’utiliser le référentiel suivant :

Sessions Actives (SA) : nombre de personnes utilisant activement des ressources du serveur. Elles sont connectées et ont appuyées très récemment sur un bouton/lien/image, ce qui impose au serveur un traitement pour lui répondre, ou bien elles viennent de se connecter sur le site et attendent en retour la homepage. Lire la suite »

VN:F [1.8.4_1055]
Rating: 0.0/10 (0 votes cast)
Partager cet article :
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Slashdot
  • Wikio FR
  • email
  • LinkedIn
  • Live
  • MySpace
  • Technorati
  • blogmarks
  • Print
  • RSS
  • Twitter
  • viadeo FR
  • Wikio

écrit par Philippe Humeau \\ tags: ,