Hébergement et scalabilité des applications PHP
Olivier Duquesne & Christian Lefebvre
(CLX / L'Autre Net / Atos Worldline)
Introduction
Une vision pluridisciplinaire La théorie avec le Club Linux NordPas de
Calais La pratique avec L'Autre Net L'expertise avec Atos Worldline
Club Linux NordPas de Calais
Association loi 1901 créée en 1999 30 bénévoles et près de 300 sympathisants La première de la région Un GULL Animation de réseau
Les GULLs amis ou partenaires Le relais AFUL La convention avec l'UFJ
Les projets de l'association
Logiciel Libre
Liberté d'exécuter Liberté d'étudier Liberté de copier et redistribuer Liberté de modifier Plusieurs licences possibles
GPL, BSD, LGPL, Cecill, Apache, PHP
Pourquoi PHP ?
Logiciel Libre Gratuit Forte communauté d'utilisateurs et développeurs :
stabilité et sécurité Facile à comprendre et utiliser Portable : Apache / ligthttpd / IIs / iPlanet / ... /
Linux / Windows / HPUX / BSD / ... Mode web ou CGI Un standard du web ?
Comment ?
Chez soit : LAMP, EasyPHP Chez un hébergeur "gratuit" : Free.fr ,
PagesPerso, ... Chez un hébergeur "associatif" : L'Autre Net,
TuxFamily, APINC, Marsnet, ... Chez un hébergeur "commercial" : OVH, Nexen,
Atos Worldline, AlterWay, ...
L'Autre Net
Association loi 1901 crée en 2001 Suite à la fermeture d'Altern Hébergeur Associatif Autogéré NonMarchand Bénévoles (root et collège solidaire) Espace de liberté Mutualisation de plateforme
AlternB
En 2001 : un serveur 1U/PIII/500M : une centaine de comptes
100 Mo (web + mail + listes + bdd) RedHat bricolée / Apache / PHP2 / Qmail / ... Usine à gaz !! Temps de réponse déplorables, une
affaire de geek Un public novice et militant (associations en tous
genres, pages perso)
AlternC (1)
En 2011, L'Autre Net c'est 10 serveurs (biXeon ou v210) , 2 serveurs de fichiers, 1 LantoLan vers Gitoyen Fibre 1Gb, monitoring externe, accès distant ....
1200 comptes, 2500 noms de domaines, des listes de diffusions, statistiques, mail, webmail, machines à la demande ...
Un transit de 5Mbs Debian, Apache, PHP5, Mailman, Awstats, Postfix,
Courier*, vServer, OSPF, IPVS, ....
AlternC (2)
Un outil simple pour les administrateurs (root) les utilisateurs (bénévoles) les usagers (membres, toujours aussi novices)
Pour tout faire : DNS, BDD, Édition, Web, ... Logiciel Libre maintenu par L'Autre Net,
Globenet, Octopuce, Koumbit Packagé (Debian), mais peu scalable ....
AlternC (3)
Sécuriser les données (1)
Depuis PHP3, le cloisonnement des données est permis grâce au safe_mode
contrainte pour l'utilisateur (de la nécessité de bien écrire)
contrainte pour l'administrateur (bien actualiser les répertoires autorisés lors de la création de comptes)
safe_mode_gid : chaque utilisateur AlternC a un GID unix pour cloisonner l'accès aux données et positionner des quotas disques
Sécuriser les données (2)
Plusieurs machines frontales (loadbalancing) Un stockage unique (NFSv3) en RAID5 Sauvegardes incrémentales et complètes
des données des bases de données
Protections des machines iptables, rootkit hunter, fail2ban, logwatch, ... memory_limit & co
Les difficultés
Une instance apache : des milliers de vhosts Un process PHP peut ralentir l'ensemble de la
plateforme. Les utilisateurs codent ce qu'ils veulent La plupart du temps, ils n'y connaissent rien et
récupèrent des applications toutes faites SPIP, Joomla, phpBB,Wordpress, ...
Problèmes courants
"Oups, j'ai tout perdu" => restauration "Je ne peux plus écrire" => full / quota "ça marche plus" => cache, DNS, restaure "ça rame" => chez moi ça marche (tm)
CPU ? RAM ? I/Owait ? In/OutRx ? MaxServer Apache Max Established Sockets Slow Query
Tuning Système (1)
Tuning Apache Augmenter le nombre de threads apache : mode
prefok : 1 thread par connexion Attention, un thread apache+PHP arrive facilement à
50 Mo en RSS Diminuer le keepalive et timeout (bonne idée si
beaucoup de RAM) Utilisation de mod_bandwith : quota BP
Tuning PHP léger finalement ...
Tuning Système (2)
Tuning OS Utilisation de eAccelerator abandonné
(dégradation sur de nombreux SPIP) Utilisation de memcached : problèmes de session
(Joomla, Moodle)
Réussites
Aide de la communauté SPIP 700 SPIP déployés, debug sur des pconnect() en
2006 hébergement de spipcontrib.net (et son départ
transparent en 2009 ...) contributions plugins SPIPMutu, SPIPTeX,
SPIPOrtho
Utilisation de memcached Aides diverses : patch Drupal, Dokuwiki, Moodle
Atos Worldline
Leader dans les transactions électroniques Spécialisé dans les paiements électroniques, les
eCS et les marchés financiers. Un chiffre d’affaires de 867 millions d’euros,
emploie plus de 5 400 personnes en Europe et en Inde et réalise plus de 15 Milliards de transactions par an.
Les chiffres en 2008
250 millions de SMS 45 Mds d’emails échangés par 23 M bàl 2 milliards de transactions d’acquisition 21 millions d’opérations de carte de crédit 100 millions de paiements internet 36 millions de cartes de fidélité 50 milliards de pages vues
Offres commerciales
Offre d'hébergement web mutualisé en silo Front/Middle/Back autour des technologies J2EE framework issus des labos R&D
Offre d'hébergement dédié à la demande : J2EE, PHP, Ruby, ... en silo Front/Middle/Back (ou pas) flexibilité
Business Unit par métier
Scalabilité
Un matériel homogène Un OS homogène (Atos LFS)
flexibilité packagé sécurité expertise
Des outils d'administration livtools servicetools referencetools
Répartition de charge applicative, matérielle, silos clônables
Cas concret : eCommerce
Une plateforme Magento Serveur Web maîtrisé
Apache 2.2.23 : le moins de modules possibles, mode prefork
PHP 5.2.5 : les options minimales, modules externalisés, sans debug
Cluster BDD : MySQL : Heartbeat en mode failover
État : 10 minutes de disponibilité en benchmark
Optimisations Système (Web)
Pile TCP : tcp_keepalive_time et tcp_syncookie
Changement ioscheduler : [deadline] cfq
Déploiement de machines supplémentaires
OpenQRM : clônage de machines Xen Templates de configurations
Mise en cache PHP : Alternative PHP Cache (APC) : cache opcode
Mise en cache SQL : memcached : 5 à 10% des hits en cache
Optimisations Système (HTTP)
Worldline Booster : mise en cache HTTP datacenter à forte connectivité : latence à
surveiller Technologie propriétaire + xcache Administration via un Web dédié (Tomcat)
Varnish : mise en cache HTTP Macros en ESI Administration via un Web dédié (Erlang) Temps de réponse divisé par 3 !
Optimisations Système (NFS)
Jumbo Frame (MTU=9000) sur client, serveur, switch
TCP, bg, hard, timeo=300 : garder la ligne
noatime : force la désactivation de l'accounting
sunrpc.tcp_slot_table_entries=128 : table de montage
rsize=32768, wsize=32768 : bits en read et write
actimeo=0 : désactivation du cache NFS
CONFIG_NFS_DIRECTIO=y (kernel)
innodb_flush_logsat_trx_commit=1 (MySQL)
innodb_flush_methods = O_DIRECT (MySQL)
minra = off (Data OnTapp)
Optimisations Base de Données
Changement de version de MySQL 5.0.46 au profit de 5.1.46 Enterprise
Atos est Gold Partner MySQL
Répartition via Heartbeat2 Outil de livraison de configuration
Industrialisation, homogénéisation
Séparation écritures / lectures via Réplication
Tuning MySQL Optimisations requêtes Magento
Optimisations query_cache_size
Compression : slave_compressed_protocol=1
Autre cas concret : Portail sportif
But : refonte intégrale d'un site lié au sport Refonte graphique + multilingue
Revue de l'ergonomie du site d'admin Dialogue avec le nouveau SI du client Module de statistiques sportives
Contrainte : tenir les pics de charge pendant les événements sportifs
Solution retenue
Architecture LAMP Framework Symfony 1.4 ORM Doctrine Plusieurs plugins :
Standards : Gestion des droits, I18N Maison : Surcharge des données, traçabilité
Pas mal de batchs (imports, prétraitements) Cache applicatif (memcached)
Déroulement des développements
Plusieurs centaines d'HJ Pas mal de mouvements dans les specs Quelques dérapages qui empêchent de bencher
suffisamment tôt
L'idéal pour avoir de mauvaises surprises en fin de projet ...
Les ORM c'est cool
On décrit ses données (via DBDesigner, en YML, directement en SQL ...)
Doctrine génère les classes de mapping et les tables SQL
Symfony génère les classes de CRUD et d'admin
En théorie, y'a plus qu'à affiner les détails
Mais c'est gourmand
84 tables et 91 « sous tables » (générées par les plugins)
568 classes auto générées et 337 surcharges 2Mo de code rien que pour le 'M' de MVC ...
Les ORM c'est cool (suite)
Les classes générées emballent les accès aux données
Doctrine::getTable('Bidule')->findOneByMachin($machin)->getMaColonne()
Mais ça masque toute la complexité :
La 1ère version de la homepage générait plus de 1000 requêtes BDD !
Et de belles horreurs bien cachées :
Doctrine::getTable('Bidule')->findByXyz(…)->getFirst()
Le select retourne éventuellement des centaines de lignes, que doctrine parse pour instancier autant d'objets qu'il peuple un par un pour finalement attraper le premier et jeter tout le reste
Le CRUD généré c'est cool
Pour chaque table, Symfony génère des classes de CRUD
Ce code contient des templates à tiroir, en quantité Un soussoustemplate peut accéder à un champ
« induit » qui entraîne une requête BDD
Mais ça fait des trucs louches
L'I18N par exemple provoque une requête sur une sous table, pour chaque itération
On se retrouve avec 1+N requêtes au lieu d'une seule
Il faut donc adapter la config des « admin generators » pour forcer des « join »
PHP, ça rame
Dès qu'il y a des algo un peu tordus, on explose les temps d'exécution
Le calcul des statistiques nécessite des calculs assez lourds, dans les « postSave »
Solution en 2 étapes : Système « producteur/consommateur » pour
« sortir » les calculs de l'admin Recodage des algos en procédures stockées
(sauvage, mais efficace)
Le cache c'est cool
Le cache de template permet d'alléger énormément la charge
Les TTL permettent de gérer facilement le renouvellement des données cachées
Mais pendant un live, il faut que les infos arrivent sur le site dès réception
Donc décache explicite, mais le plus fin possible (si on décache trop large en pleine charge, on explose tout)
Ça implique des règles très complexes
Memcached c'est cool
Permet de stocker des éléments en cache Tous les fronts peuvent accéder au même cache
et le décache peut être déclenché de partout On peut stocker des milliers d'éléments sans
pertes de perfs Mais le protocole ne permet pas de delete par
pattern
Mais symfony réserve des surprises
Alors comment symfony implémente la méthode removePattern() ?
Une entrée « meta » stocke la liste des clés de toutes les entrées (donc potentiellement des milliers)foreach ($this->getCacheInfo() as $key) { if (preg_match($regexp, $key)) { $this->remove(substr($key, strlen($this->getOption('prefix')))); }}
Et paf le php ...
Et maintenant, qu'estce qu'on fait ?
Séparez en plugins qu'on active seulement dans les applis nécessaires (pour éviter de charger du code inutile)
Évitez de générer du code inutile(dans schema.yml) symfony: { form: false, filter: false }
Testez et benchez dès le début, comptez les requêtes et analysez les pour détecter les appels cachés avant qu'ils se fondent dans la masse
Prenez en compte le cache dès le début
N'ayez confiance en personne, même pas dans les produits les plus réputés :)
Quelques outils utiles MemCached, CouchDB et autres NoSql
Varnish (ESI notamment)
APC (pour l'opcode, mais aussi le cache local)
Procédures stockées (un curseur va plus vite qu'une boucle PHP)
Symfony Web Debug Toolbar (logs et détails sur les requêtes SQL)
netstat, ps, gdb … et autres outils de diagnostic car les soucis n'apparaissent souvent qu'en vraie charge
Jmeter et autres outils de bench
Xdebug (profiling)
Ressources
Qui sommes nous ? Club Linux NordPas de Calais : http://clx.asso.fr L'Autre Net : http://lautre.net Atos Worldline : http://www.atosworldline.fr
Les outils Varnish : http://www.varnishcache.org Symfony : http://www.symfonyproject.org Doctrine : http://www.doctrineproject.org Heartbeat : http://www.linuxha.org
Questions ?
Olivier Duquesne : [email protected] Christian Lefebvre :
CLX : [email protected] L'Autre Net : [email protected]
Top Related