M1 CERI Avignon 2010/2011. Rapport. Optimisation/Sécurité d un serveur Web NGINX/PHP/MySQL. Cyril CADET/Habib BAKAKAS

Documents pareils
Synchronisation Mysql (Replication)

Architectures haute disponibilité avec MySQL. Olivier Olivier DASINI DASINI - -

MySQL - Réplication. Fichiers de relais et de statut de la réplication. Mise en place de la réplication

Architecture de la plateforme SBC

L installation a quelque peu changée depuis les derniers tutos, voici une actualisation.

PHP. Performances. Audit et optimisation LAMP. Julien Pauli. Cyril Pierre de Geyer. Guillaume Plessis. Préface d Armel Fauveau

Pratique et administration des systèmes

windows. deb etch main deb-src etch main

Ocs Inventory et GLPI s appuie sur un serveur LAMP. Je vais donc commencer par installer les paquets nécessaires.

Tutoriel compte-rendu Mission 1

Installation d'un serveur FTP géré par une base de données MySQL

Installation de Zabbix

Olivier Mondet

MANUEL D INSTALLATION D UN PROXY

Client windows Nagios Event Log

INTRODUCTION. Mysql-server est un serveur de bases de données. Cest un logiciel libre.

Haute disponibilité des données

Notes de cours : bases de données distribuées et repliquées

Mysql. Les requêtes préparées Prepared statements

Gestion d identités PSL Exploitation IdP Authentic

07/03/2014 SECURISATION DMZ

Pharmed. gestion de pharmacie hospitalière. Installation / déploiement

Service WEB, BDD MySQL, PHP et réplication Heartbeat. Conditions requises : Dans ce TP, il est nécessaire d'avoir une machine Debian sous ProxMox

Configurer la supervision pour une base MS SQL Server Viadéis Services

Installation UpdatEngine serveur (CentOs apache2 / MySQL)

Network Shutdown Module V3 Extension du Manuel Utilisateur pour architecture Virtualisée VMWare ESX Server 3, 3.5

Serveur Linux : FTP. Mise en place d un service FTP sous Linux. Bouron Dimitri 20/04/2014

Guide Installation Serveur Extensive Testing

MySQL. (Administrateur) (Dernière édition) Programme de formation. France, Belgique, Suisse, Roumanie - Canada

Afin d'éviter un message d'erreur au démarrage du service Apache du type :

Installation et Mise en œuvre de MySQL

Guide Installation Serveur Extensive Testing

TP LINUX : MISE EN PLACE DU SERVEUR DE MESSAGERIE QMAIL

1 Configuration des Fichiers Hosts, Hostname, Resolv.conf

TP Service HTTP Serveur Apache Linux Debian

Tuto 2 : Configuration Virtual box, Configuration et installation du serveur XiBO

Maintenance et gestion approfondie des Systèmes d exploitation Master 2 SILI. Année universitaire David Genest

Comment Accéder à des Bases de Données MySQL avec Windows lorqu'elles sont sur un Serveur Linux

Network Shutdown Module V3 Extension du Manuel Utilisateur pour architecture Virtualisée VMWare ESX Server

GOUTEYRON ALEXIS. SIO2 N candidat: UEpreuve E4. USituation professionnelle 2. serveurs de fichiers. Uen haute disponibilité

GLPI OCS Inventory. 1. Prérequis Installer un serveur LAMP : apt-get install apache2 php5 libapache2-mod-php5 apt-get install mysql-server php5-mysql

Cellier Clément, Maginot Quentin, Tripier Axel, Zaorski Jean, Zini Robin. 18 mars 2015

BTS SIO SISR3 TP 1-I Le service Web [1] Le service Web [1]

Configuration matériel. Tâche 2 : Installation proprement dite de l application sur un serveur de test virtualisé sous VmWare Workstation.

Installation d OwnCloud 8.0 sous Debian Avec connexion des utilisateurs active directory et mise en place de HTTPS

ORACLE 10G DISTRIBUTION ET REPLICATION. Distribution de données avec Oracle. G. Mopolo-Moké prof. Associé UNSA 2009/ 2010

BTS SIO Dossier BTS. PURCHLA Romain

Stockage du fichier dans une table mysql:

Bind, le serveur de noms sous Linux

MYSQLDUMP & ZRM COMMUNITY

Installation et configuration d OCS/GLPI sur un Serveur Debian

Notes pour l'installation d'une version de Eprints sur une machine CentOS4.2 Stéphanie Lanthier Le jeudi 17 février 2006

WEB page builder and server for SCADA applications usable from a WEB navigator

Hébergement de site web Damien Nouvel

Documentation d'installation Plateforme femme actuelle

REPARTITION DE CHARGE LINUX

INFO-F-404 : Techniques avancées de systèmes d exploitation

Table des matières. 1. Installation de VMware ESXI Pré-requis Installation... 3

MariaDB/MySQL Avancé. Pierre Mavro Creative Commons License

INSTALLATION NG V2.1 D OCS INVENTORY. Procédure d utilisation. Auteur : GALLEGO Cédric 23/10/2014 N version : v1

titre : CENTOS_CUPS_install&config Système : CentOs 5.7 Technologie : Cups Auteur : Charles-Alban BENEZECH

Procédure d'installation

04/02/2014 Tutoriel. Lubuntu & glpi. thomas [NOM DE LA SOCIETE]

MySQL 5.6. Performances et Tuning. MySQL Performances et Tuning. MySQL 5.6. Vincent TAHON

Le protocole FTP (File Transfert Protocol,

Encryptions, compression et partitionnement des données

INSTALLATION DE WINDOWS 2000 SERVER POUR BCDI3. par. G.Haberer, A.Peuch, P.Saadé

PHP et mysql. Code: php_mysql. Olivier Clavel - Daniel K. Schneider - Patrick Jermann - Vivian Synteta Version: 0.9 (modifié le 13/3/01 par VS)

Guide pour l Installation des Disques Durs SATA et Configuration RAID

PPe jaune. Domingues Almeida Nicolas Collin Leo Ferdioui Lamia Sannier Vincent [PPE PROJET FTP]

Configuration de plusieurs serveurs en Load Balancing

Installation de VirtualPOPC-1 sur Ubuntu Server LTS 64bits

Installation du serveur WEB Apache ( MySQL, PHP) sous Debian 7.

Open Source Job Scheduler. Installation(s)

Sybase High Avalaibility

Titre: Version: Dernière modification: Auteur: Statut: Licence:

Cluster High Availability. Holger Hennig, HA-Cluster Specialist

Titre: Version: Dernière modification: Auteur: Statut: Licence:

Imprimantes et partage réseau sous Samba avec authentification Active Directory

Installation de Smokeping sur Debian

Couche application. La couche application est la plus élevée du modèle de référence.

1-Introduction 2. 2-Installation de JBPM 3. 2-JBPM en action.7

Guide d'installation et de configuration de Pervasive.SQL 7 dans un environnement réseau Microsoft Windows NT

Automatisation de l administration système

Installer un serveur web de développement avec VirtualBox

Perl Console. Votre compagnon pour développer en Perl. Les Journées du Perl , 17 novembre, Lyon. Alexis Sukrieh

Installer un domaine DNS

Sendmail milter/greylisting

laposte.net) Ministère de l'éducation nationale Atelier sécurité Rabat RALL 2007

Préparation d un serveur Apache pour Zend Framework

Installation d un serveur HTTP (Hypertext Transfer Protocol) sous Débian 6

Présentation Alfresco

TARDITI Richard Mise en place d une Haute Disponibilité

Cloner un disque dur

Manuel de l Administrateur

Audit et optimisation MySQL 5

Transcription:

M1 CERI Avignon 2010/2011 Rapport Optimisation/Sécurité d un serveur Web NGINX/PHP/MySQL Cyril CADET/Habib BAKAKAS 2011

Contenu 1. Remerciements... 3 2. Avant-propos... 3 3. Introduction... 3 4. Architecture... 4 5. Serveur Web Nginx... 5 5.1. Principe de l URL Rewriting... 5 5.2. Optimisation... 6 6. Serveur PHP... 8 6.1. PHP-FPM... 8 6.2. PHP-FPM avec Nginx... 9 6.3. Benchmark de PHP-FPM... 9 Test 1... 9 Test 2... 10 Conclusion sur les Test... 11 6.4. Les cache d opcode... 11 Exemple d opcode... 11 6.5. APC : Alternative PHP Cache... 12 Test... 13 Comparatif... 13 7. MySQL... 14 7.1. Les moteurs de tables... 14 Transactions... 14 InnoDB... 14 XtraDB (Percona Server)... 14 7.2. InnoDB vs XtraDB... 15 Test 1 : InnoDB (MySQL) vs xtradb (Percona)... 15 7.3. Optimisation my.cnf... 16 1

Test 2 : fichier my.cnf optimisé... 17 8. Disponibilité/Robustesse... 18 8.1. Réplication Master/slave temps réel MySQL... 18 9. MySQL Cluster... 19 9.1. Architecture de Mysql Cluster... 19 9.2. Caractéristiques de mysql Cluster... 21 10. Problèmes Rencontrés... 25 11. Bilan... 25 12. ANNEXE... 26 12.1. Mise en place de NGINX+PHP-FPM... 26 Installation... 26 Script de démarrage... 26 12.2. Mise en place de APC... 28 Installation... 28 12.3. Mise en place de Percona Serveur... 28 Installation... 28 12.4. Mise en place de la réplication Master/Slave... 29 Près Requis... 29 Coté Master... 29 Coté Slave... 30 12.5. Mise en place de mysql cluster... 31 2

1. Remerciements Nous remercions nos trois tuteurs : Benjamin Maza, Stanislas Oger et Pierre Gotab pour nous avoir accompagnés et conseillés, lors de ce projet. Nous leurs en sont très reconnaissant d avoir su régler les problèmes techniques lorsqu il y en avait. 2. Avant-propos Nous participons au développement et à la mise en production d un jeu de stratégie Web moderne (Ajax/jQuery, php5/symfony/doctrine) utilisant des techniques innovantes. Plus précisément nous déterminerons l'architecture réseau (serveur web, MySQL, PHP) permettant un fonctionnement optimal du jeu de stratégie. Nous avons au premier semestre fait l étude de la technologie de serveur web que nous allons adoptée (grâce aux différents benchmarcks). Ce rapport va montrer un descriptif sur l optimisation de notre serveur Web, serveur PHP, serveur MySQL pour qu il puisse supporter une charge importante. Il va également traiter de la partie robustesse en traitant la réplication MySQL ainsi que la sécurisation du serveur Web. 3. Introduction Devant un nombre croissant de connexions, les performances des serveurs Web s'effondrent. Afin d'améliorer les temps de réponse, le premier réflexe est généralement de dissocier le serveur HTTP et la base de données. Une solution tout aussi courante consiste à augmenter le nombre de serveurs HTTP en utilisant des solutions de «load balancing». Si ces solutions se montrent généralement efficaces, elles restent néanmoins coûteuses en termes de matériel et d'hébergement. De plus, elles sont parfois complexes à mettre en œuvre. Pourtant d'autres solutions trop souvent méconnues existent. C est en particulier le cas des «optimiseurs» et des systèmes de cache («opcode» ou fichiers). Plusieurs solutions sont alors envisageables : augmenter la puissance des serveurs, modifier l architecture en déportant les bases de données sur d autres serveurs, rajouter des serveurs et mettre en place une 3

Cache APC Cache SQL M1 CERI Rapport 2010-2011 solution de load-balancing Solutions qui peuvent s avérer efficaces dans une certaine mesure tout au moins mais dont le coût est lui à coup sûr exponentiel, d autant que ces solutions vont généralement demander une revue de code et des modifications ou ajustements plus ou moins lourds. Autre solution : utiliser le serveur web Nginx. 4. Architecture L'optimisation d'un serveur web est un élément important dans le temps de chargement d'une page web par le navigateur pour permettre une montée en charge importante. Notre architecture est composée de 3 étages : le serveur web (nginx), qui reçoit la requête http et renverra la réponse finale vers le client le moteur PHP-FPM, qui exécute des instructions côté serveur (php,ruby,c++,...) et génère le html résultant la base de données qui stocke les informations qui vont permettre de générer la page finale. Index.php SELECT * FROM WHERE Serveur Web PHP-FPM Base de données html «nom objet», «bouclier» 4

Pour améliorer les performances de l'ensemble de cette architecture, il est possible d'intervenir sur ses différents étages. Première optimisation possible, est de répartir la charge des 3 étages de la chaîne du service web, sur 3 serveurs. C'est coûteux, mais nécessaire pour les gros sites. La seconde optimisation de la performance possible, est d'éviter la sollicitation de chaque étage, pour avoir une réponse rapide. Pour cela, on va utiliser des applications caches, qui vont stocker les éléments déjà générés, voici quelques exemples : Le cache SQL, va stocker la réponse à des requêtes déjà exécutées précédemment, ainsi, on évite d'interroger la base de données. les caches d opcode (apc, xcache,eaccelerator...), vont garder en mémoire les opcodes générées et ainsi éviter a PHP la conversion des instructions en opcodes. 5. Serveur Web Nginx 5.1. Principe de l URL Rewriting Le principe de la réécriture d'url est de mettre en place un «système» sur le serveur pour qu'il sache interpréter ce nouveau format d'url. Dans notre exemple, quand un visiteur accède à la page http://www.notre-site.com/articles/article-12-2-5.html, le serveur doit renvoyer exactement la même chose que si le visiteur avait demandé à accéder à la page http://www.notresite.com/articles/article.php?id=12&page=2&rubrique=5. La correspondance entre les deux schémas d'url est alors décrite sous forme de «règles de réécriture». Chaque règle permet de décrire un format d'url. Dans l'exemple ci-dessus, la règle de réécriture va indiquer au serveur de prendre le premier nombre comme numéro d'article, le deuxième comme numéro de page et le troisième comme numéro de rubrique. 5

5.2. Optimisation On édite le fichier /etc/nginx/nginx.conf pour voir sa configuration : user www-data; worker_processes 2; events { worker_connections 2048; } http { include default_type mime.types; application/octet-stream; sendfile on; keepalive_timeout 30; tcp_nodelay on; gzip on; gzip_disable "MSIE [1-6].(?!.*SV1)"; gzip_vary on; gzip_comp_level 3; gzip_proxied any; gzip_buffers 16 8k; } include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; Explication principales directives de nginx.conf : worker_processes 2 : C est le nombre de processus actif à engendrer. Ce processus est similaire au processus fils dans apache. Nginx à la capacité d utiliser plusieurs processus actifs sur des machines dotés de plusieurs processeurs. En général le nombre de processus actifs doit correspondre au nombre de processeurs de la machine. Pour calculer le nombre total de connections simultanées que nginx peut supporter, on multiplie le "worker_processes" par le "worker_connections". Dans notre cas nous obtenons 2048. Après que 2048 clients soient connectés les clients supplémentaires seront rejetés. worker_connections 2048 : C'est le nombre de connections clientes qu un seul processus fils contrôlera (1024 par défaut ). Note : multiplier le nombre de processus actifs par le nombre de connections actives nous donne le nombre total de connections gérées par nginx. Dans notre exemple le serveur est conçu pour gérer 4096 connections. Les clients se connectant après que le max ait été atteint n'auront pas de connection. MIME types : Cette section permet à nginx d'identifier les fichiers par leur extensions. Par exemple si le serveur renvoie un fichier d'extension.txt, alors le type mime sera défini comme text/plain. 6

include mime.types : est le fichier de définition que nginx charge pour identifier tous les types mime. Cette directive permet simplement au serveur d'envoyer les types de fichiers et d'applications appropriés aux clients. types {...} : Au lieu d'utiliser la directive «include mime.types» on peut définir nos propres types mime. C'est une option particulièrement utile si on veut utiliser les même types mime sur plusieurs systèmes différents ou si on nen veut pas dépendre d'un second fichier de définition. On a aussi la possibilité de définir un type mime pour une extension non standard. Par exemple nous définissons l'extension bob comme un text/plain. default_type application/octet-stream : est le type par défaut si aucune extension de fichier n'a été définie dans les types mime. C'est utile lorsque le serveur renvoie des fichiers sans extension ou d'une extension non standard. Ainsi les clients pourrons récupérer le fichier non corrompu. Size Limits : Cette directive spécifie la taille de tampon limitant la quantité de données que le serveur considérera comme valide pour une requête, par exemple si le client envoie trop de données en une requête alors la requête sera rejetée. client_body_buffer_size 1k Si le corps de la requête est supérieur au tampon alors le corps entier de la requête ou une partie sera écrit dans un fichier temporaire client_header_buffer_size 1k est la limite de la taille de toute les entête http que le client peut envoyer au serveur. Pour la grande majorité des requêtes, une taille de tampon de 1K est suffisante client_max_body_size 1k est la taille maximale du corps de la requête client, indiquée par la ligne «Content-Length» dans l'entête de la requête. Si la taille excède cette valeur le client reçoit une erreur (413) Entité requise trop grande. Timeouts : C est le temps en secondes pendant lequel nginx attendra que le client ait achevé son action server_tokens off : Cache la version du serveur nginx dans les pages d erreur autogénérées dans le cas on ne voudrait cette information pour des raisons de sécurité. gzip on : Permet la compression des fichiers gzip_static on: Permet d envoyer des fichiers.gz précompressés au lieu de compresser les fichiers à la volée. C est la façon la plus efficace de servir des données compressés. Pour utiliser cette option il faut avoir une copie compressée du fichier html à envoyer. gzip_buffers 16 8k : Spécifie la taille des tampons pour répondre aux clients qui demandent des données précompressées. 7

6. Serveur PHP 6.1. PHP-FPM PHP-FPM (FastCGI Process Manager) est une implémentation de PHP FastCGI apportant de nouvelles fonctionnalités et intégré depuis PHP 5.3.3. En CGI, un processus est exécuté à chaque nouvelle requête et un nouvel environnement d exécution est créé à chaque fois. Cette approche peut vite devenir pénalisante pour les performances, c est pourquoi FastCGI a choisi de s appuyer sur un nombre déterminé de processus pour traiter toutes les requêtes. Avec PHP-FPM, c est la même logique qui est appliquée avec quelques avantages ou fonctionnalités supplémentaires : Une création dynamique des processus (en fonction de la charge). Des statistiques. A la suite de l installation de PHP5-FPM, les fichiers de configuration se situent dans /etc/php5/fpm/php5- fpm.conf. Ci-dessous les paramètres importants : En dynamic, pm.max_children est le nombre maximum de processus, pm.start_servers le nombre au démarrage, pm.min_spare_servers le nombre minimum de processus inactifs, pm.max_spare_servers le nombre maximum de processus inactifs. pm = dynamic pm.max_children = 50 pm.start_servers = 10 pm.min_spare_servers = 5 pm.max_spare_servers = 50 pm.status_path indique l URL qui sera utilisée pour obtenir le statut du processus (à la mod_status) : pm.status_path = /status Processus tué après avoir traité 500 requêtes pm.max_requests = 500 slowlog permet de loguer les requêtes qui dépassent request_slowlog_timeout : request_slowlog_timeout = 30 slowlog = /var/log/php5-fpm.log.slow 8

6.2. PHP-FPM avec Nginx Nginx intègre par défaut le paramétrage nécessaire pour fonctionner en FCGI. La configuration est présente dans le fichier /etc/nginx/fastcgi.conf (ou /etc/nginx/fastcgi_params). Dans cette configuration, on peut se passer complètement d Apache, nginx traitant tous les fichiers statiques et passant la main à PHP-FPM pour les fichiers dynamiques (en PHP). Pour traiter les fichiers PHP, il faudra ajouter dans la configuration de vos sites des lignes du type : location ~ \.php$ { include /etc/nginx/fastcgi_params; fastcgi_pass 127.0.0.1:9000; } Cette configuration indique à tous les fichiers portant l extension.php d utiliser le fichier de configuration cité ci-dessus, et le processus PHP-FPM écoutant sur le même serveur et sur le port 9000. 6.3. Benchmark de PHP-FPM Nous allons simuler un nombre maximum de 3000 requêtes avec 40 connexions simultanées accédant à la ressource index.php (script symphony) et regarder les performances du serveur Web. Ces tests ont été réalisés 5 fois pour avoir une moyenne des résultats. Requête de benchmark avec l outil apache bench : ab -n 30000 -c 40 http://localhost/sf_sandbox/web/index.php Test 1 Ce test a été fait en gardant la configuration par défaut de PHP-FPM (Création de 50 processus PHP). Le résultat moyennant de ce test est : 87 nb requêtes/seconde. Cela signifie que le serveur traite une moyenne de 87 requêtes utilisateurs par seconde. 9

PHP-FPM defaut 89,5 89 88,5 88 87,5 87 86,5 86 85,5 85 84,5 1 2 3 4 5 nb requêtes/seconde Test 2 Ce test a été fait en mettant le nombre de processus maximum de PHP-FPM à 100. Le résultat moyennant de ce test est : 87,4 nb requêtes/seconde. PHP-FPM (100 process) 89,5 89 88,5 88 87,5 87 86,5 86 85,5 85 84,5 1 2 3 4 5 nb requêtes/seconde 10

Conclusion sur les Test D autres test ont été effectué (n3000 c100, n3000 c40, n3000 c10), il semblerait que le nombre de requêtes traitées par le serveur est d environ 90 requêtes par secondes. L augmentation du nombre de processus PHP ne semble pas faire augmenter les performances du serveur. Le temps de traitement entre le serveur nginx et les clients peut être négligé tandis que le temps de traitement du serveur PHP semble être le facteur déterminant. Le traitement par PHP-FPM est le même que ce soit pour 10 requêtes ou pour 1000. 6.4. Les cache d opcode Une partie importante du temps de traitement d'une page, servie via HTTP avec un langage de script dynamique comme PHP, provient du fait que ce langage doive transformer un code lisible par un humain, en un code exécutable par une machine virtuelle et le microprocesseur de la machine physique. Des processus lourds interviennent alors, comme l'analyse syntaxique du code source et sa transformation en un code binaire compréhensible par la machine. Ceci étant coûteux, beaucoup de langages mettent ce code binaire en cache lors du traitement de la première requête, afin de sauter toutes ces étapes les fois suivantes. Lors de l exécution d un script, PHP5 procède ainsi : il charge l intégralité du script il convertit les instructions en opcodes (sorte de langage intermédiaire entre le script et un exécutable), il exécute les instructions. Lorsqu'un même script est appelé plusieurs fois, ces opérations sont renouvelées. Ceci est une perte de temps évidente. Les solutions de cache d opcode se proposent donc d effectuer une mise en cache des opcodes, afin d en garder une trace. Ceci permet à PHP5 de les exécuter directement. Exemple d opcode code source PHP <?php $output = 'Hello World'; 11

if($_get['exclaim']) { $output.= '!'; } else { $output.= '.'; } echo $output;?> OPCode PHP 1 ASSIGN!0, 'HELLO+WORLD' 2 FETCH_R GLOBAL $1, '_GET' 3 FETCH_DIM_R $2, $1, 'exclaim' 4 JMPZ $2, ->6 5 ASSIGN_CONCAT!0, '%21' 6 JMP ->7 7 ASSIGN_CONCAT!0, '.' 8 ECHO $0 9 RETURN 1 10 ZEND_HANDLE_EXCEPTION Comme on peut le voir, les OPCodes utilisent toujours plus de place que le code PHP, environ 25 à 33%. Cett remarque est importante lorsqu'il s'agira de configurer le cache, car sa taille sera alors à calculer pour le code intermédiaire et non le code PHP. 6.5. APC : Alternative PHP Cache Les caches d'opcodes permettent des économies de travail coté serveur, ce qui se manifeste par une accélération de la réponse des pages PHP pour l'utilisateur final. APC est "l'alternative PHP Cache", un cache libre, gratuit et robuste pour mettre en cache et optimiser le code intermédiaire PHP aussi appelé "OPCode". APC est activement maintenu dans PECL et sera intégré par défaut avec PHP6. 12

Test Le protocole de test est le même qu avec PHP-FPM (la requête de Apache Bench sera la même ainsi que le nombre de test effectués). Nous obtenons une moyenne de 408 requêtes traitées par seconde par le serveur. 414 PHP-FPM avec APC 412 410 408 406 nb requêtes/seconde 404 402 400 1 2 3 4 5 Comparatif Nous pouvons constater un gain de 478%. Les performances viennent du fait de la lecture du cache d opcode et ainsi éviter une recompilation des instructions en opcode pour le traitement PHP. 450 400 350 300 250 200 150 100 50 0 Comparatif 1 2 3 4 5 APC PHP-FPM defaut PHP-FPM 100 process 13

7. MySQL 7.1. Les moteurs de tables MySQL supporte plusieurs moteurs de stockage, qui gère différents types de tables. Les moteurs de tables MySQL peuvent être transactionnels ou non-transactionnels. Transactions Le but des transactions est de s'assurer que tous les changements dans une base de données ont été correctement effectués avant de les appliquer définitivement (COMMIT). Et en cas de problèmes les transactions permettent de revenir en arrière (ROLLBACK). L application du jeu étant une application sensible, il est impératif de pouvoir gérer les transactions. InnoDB InnoDB fournit à MySQL un gestionnaire de table transactionnelle (compatible ACID), avec validation (commits), annulations (rollback) et capacités de restauration après crash. Ces fonctionnalités accroissent les possibilités d'utilisation simultanées des tables, et les performances. Il n'y a pas de problème de queue de verrous avec InnoDB, car les verrous de lignes utilisent très peu de place. Les tables InnoDB sont les premières tables MySQL qui supportent les contraintes de clés étrangères (FOREIGN KEY). InnoDB a été conçu pour maximiser les performances lors du traitement de grandes quantités de données. Techniquement, InnoDB est un gestionnaire de table placé sous MySQL. InnoDBdispose de son propre buffer pour mettre en cache les données et les index en mémoire centrale. InnoDB stocke les tables et index dans un espace de table, qui peut être réparti dans plusieurs fichiers. XtraDB (Percona Server) Percona Server avec XtraDB est une version améliorée du serveur de base de données MySQL. Il est basé sur le populaire engine InnoDB, mais offre de meilleures performances tout en demeurant 100% compatible 14

à ce que InnoDB peut accomplir. On peut donc remplacer aveuglement InnoDB par XtraDB sans craindre quoi que ce soit! On pourrait ainsi dire qu il s agit d un nouveau InnoDB, plus rapide et plus robuste. 7.2. InnoDB vs XtraDB Plus de transactions parallèles disponibles InnoDB fournit un nombre fixe de 1024 slots dans son segment d annulation (contient les anciennes valeurs des enregistrements en cours de modification dans la transaction), laissant ainsi se dérouler 1024 transactions en parallèles. Si tous les slots sont utilisés, n importe quelle nouvelle transactions échouera jusqu à la libération d un nouveau slots. Ce qui peut occasionner des comportements étranges de la table. Le changement de variable nous permet d étendre le nombre de ces slots à 4072 sur XtraDB permettant ainsi d augmenter le nombre de transactions parallèle. Les améliorations de ce moteur de table sont disponibles à l adresse suivante : http://www.percona.com/docs/wiki/percona-server:features:start Test 1 : InnoDB (MySQL) vs xtradb (Percona) Pour comparer les deux moteurs de tables nous simulons un nombre de 3000 utilisateurs réalisant 30 requêtes simultanées. ab -n 3000 -c 30 http://localhost:80/bench_bdd_innodb.php 15

78 76 74 72 70 68 66 InnoDB XtraDB 64 62 60 1 2 3 4 5 Nb de requêtes/s Nous constatons un gain non négligeable de la part du moteur de Percona. 7.3. Optimisation my.cnf Le fichier ce configuration de MySQL se situe dans : /etc/mysql/my.cnf innodb_buffer_pool_size=1g //utiliser un buffer de taille de 50% de la mémoire serveur innodb_additional_mem_pool_size=16m innodb_data_file_path=ibdata1:10m:autoextend // Cette configuration crée un fichier de données de 10 Mo ibdata1, auto-croissant. Il n'y a pas de dossier de sauvegarde d'indiqué : par défaut, c'est le dossier de données de MySQL. Une table contenant 50 Mo de données, appelée ibdata1 innodb_file_per_table=1 #Utilisez..flush_log_at_trx_commit #à 0 si vous pouvez accepter de perdre #quelques transactions innodb_flush_log_at_trx_commit=1 innodb_log_file_size=150m //utiliser un fichier de log de taille de 15% du buffer mémoire 16

Test 2 : fichier my.cnf optimisé 1200 1000 800 600 400 XtraDB xtradb Optimisé 200 0 1 2 3 4 5 L utilisation d un cache InnoDB améliore grandement les performances du serveur. Cependant pour avoir de meilleures performances et optimiser au mieux le fichier de configuration, il existe des outils comme mysqltuner qui permettent d analyser l utilisation qui est faite de la base et proposer les options appropriées. 17

8. Disponibilité/Robustesse 8.1. Réplication Master/slave temps réel MySQL La réplication MySQL consiste à avoir deux bases de données MySQL identiques. La réplication MySQL est basée sur le fait que le serveur va garder la trace de toutes les évolutions de vos bases (modifications, effacements, etc.) dans un fichier de log binaire et les esclaves vont lire les requêtes du maître dans ce fichier de log, pour pouvoir exécuter les mêmes requêtes sur leurs copies. Il est très important de comprendre que le fichier de log binaire est simplement un enregistrement des modifications depuis un point fixe dans le temps (le moment où vous activez le log binaire). Tous les esclaves que vous activez auront besoin de la copie des données qui existaient au moment du démarrage du log. Si vous démarrez vos esclaves sur sans qu ils ne disposent des données identiques à celles du maître au moment du démarrage du log binaire, votre réplication va échouer. Nous partons avec l architecture suivante: Deux serveurs A, et B sous Linux (réalisé sous Debian) ayant chacun une base de donnée MySQL. IP Serveur Master : 10.104.3.1 IP Serveur Slave : 10.105.3.1 Master Slave Les avantages d une architecture comprenant 1serveur physique (architecture verticale) comprenant 1web (nginx), 1 serveur PHP (PHP-FPM), 1 serveur MySQL (Percona) sont : - Moins couteux en termes de matériel - Plus simple à déployer 18

- On peut lui associer un autre serveur physique pour réaliser la duplication de la base (sécurité des données) - Efficace 9. MySQL Cluster Mysql cluster est une solution d'architecture de stockage de données distribuées, étanche ( shared nothing), conçue pour la haute performance et la tolérance aux fautes. Les données sont stockées et répliquées sur des nœuds de données individuels (nœuds de stockage), ou chaque nœud de données s'exécute sur un serveur séparé et maintiens une copie des données. Chaque cluster contient aussi de nœuds de contrôle (management nodes). Au sein du cluster les updates utilisent une isolation à la lecture pour s'assurer que tous les nœuds ont des données correctes et un commit à deux phases pour s'assurer que les nœuds ont des données identiques (si l'écriture d'un nœud échoue, le update associé échoue aussi) Le concept d'étancheité et de noeuds de données pair à pair permet à un update executé sur un serveur d'être visible immédiatement sur les autres serveurs. Le but est d'avoir la performance la plus élevée possible en utilisant plusieurs serveurs mysql pour distribuer la charge, une haute disponibilité et redondance en stockant les données à différents endroits. Une installation typique de mysql Cluster implique d installer les composants mysql sur différentes machines du réseau. Ainsi, le terme mysql cluster renvoie au serveur mysql et aux composants ndb (network database). Un moteur de stockage appelé NBDcluster est l interface qui lie le serveur mysql aux éléments du cluster. 9.1. Architecture de Mysql Cluster On peut voir le cluster Mysql comme ayant trois couches : Les applications qui communique avec le serveur mysql Le serveur mysql qui traite les commandes sql et communique avec le moteur de stockage ndb 19

Les composants du cluster ndb (aussi appelés nœuds de données) qui traitent les requêtes et renvoient les résultats au serveur Mysql Il est possible d utiliser plusieurs serveurs mysql pour se connecter à un seul cluster ndb ou plusieurs clusters ndb via la réplication mysql. Cluster ndb avec 4 nœuds et un serveur mysql 20

9.2. Caractéristiques de mysql Cluster Pour satisfaire les buts de haute performance, haute disponibilité, et de redondance, les données sont répliquées parmi les nœuds de données d une façon synchrone. La réplication mysql, par contre, est asynchrone. La réplication asynchrone sera utilisée lors de la réplication de plusieurs clusters. La réplication asynchrone signifie qu il existe un délai dans la mise à jour des esclaves, en effet les esclaves ne reportent pas la progression dans la validation des changements et nous n avons donc pas de vue cohérente des données sur toute l architecture répliquée comme cela est le cas dans un cluster. Le cluster mysql a plusieurs propriétés lui permettant de créer un système à haute disponibilité, les plus importantes sont : Rétablissement de nœud Une défaillance d un nœud de données peut être détectée via une perte de communication ou un échec du heartbeat, et il est possible de redémarrer automatiquement en utilisant des copies de données de nœuds restants Rétablissement du système Dans l éventualité que le système entier soit indisponible suite à un aléa, le système peut être restauré à partir des logs de changement et les données sont alors copiés des disques à la mémoire. Failover Pour assurer que le recouvrement de nœuds est possible, toutes les transactions sont validées en utilisant une protection en lecture et un commit à deux phases. Les transactions sont ainsi doublement protégées car stockées en deux endroits différents avant que la transaction ne soit validée. Partitionning Les données sont automatiquement partitionnées sur les nœuds de données. 21

Comme nous avons vu précédemment, il est possible de créer une redondance globale utilisant la réplication mysql entre les clusters (v. fig. ci-dessous) Un cluster mysql se compose de : Mysqld Le serveur mysql NDBd Un nœud de données NDBmtd Un nœud de données supportant le multithread 22

NDB_mgmd Serveur de contrôle du cluster NDB_mgm Client de contrôle du cluster On peut évaluer la taille de la mémoire nécessaire pour un cluster en utilisant le script perl NDB_size.pl. Ce script se connecte à un serveur mysql en fonctionnement et évalue ses tables existantes et calcule la mémoire qu elles nécessiteraient dans un cluster mysql. 23

Ci-dessous la figure représente un cluster mysql dans un scenario de haute disponibilité dans un service web : Dans ce scenario de haute disponibilité nous introduisons la réplication externe à plusieurs chaines qui nous permet d introduire de la redondance dans la réplication asynchrone entre maitre et esclave. 24

10. Problèmes Rencontrés De nombreux problèmes systèmes nous ont ralentie (problèmes lors de l installation de nouveaux paquets, problèmes de dépendances, problèmes lors des compilations). 11. Bilan Ce projet est un projet conséquent en termes de technologie et d innovation. Il existe une multitude d approches à avoir pour l optimisation en termes d architecture et en termes d application (nombreux logiciels). Il aurait été intéressant de posséder la base complète du jeu et de pouvoir la tester dans de vraies conditions. Cela nous aurait permis d être certain de l architecture à adopter (verticale ou horizontale) en vue des résultats obtenus. 25

12. ANNEXE 12.1. Mise en place de NGINX+PHP-FPM Installation # Près-requis apt-get install build-essential libpcre3-dev libssl-dev zlib1g-dev apt-get install php5-cli php5-common php5-mysql php5-suhosin php5-fpm php5-cgi php-pear php5-gd php5-curl # Téléchargement des fichiers wget http://sysoev.ru/nginx/nginx-0.8.54.tar.gz # Extraction tar zxvf nginx-0.8.54.tar.gz # Configure cd nginx-0.8.54./configure \ --conf-path=/etc/nginx/nginx.conf \ --error-log-path=/var/log/nginx/error.log \ --pid-path=/var/run/nginx.pid \ --lock-path=/var/lock/nginx.lock \ --http-log-path=/var/log/nginx/access.log \ --with-http_dav_module \ --http-client-body-temp-path=/var/lib/nginx/body \ --with-http_ssl_module \ --http-proxy-temp-path=/var/lib/nginx/proxy \ --with-http_stub_status_module \ --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \ --with-debug \ --with-http_flv_module \ # Compilation make # Installation make install # Création des repertoires que l on a besoin mkdir /var/lib/nginx mkdir /etc/nginx/conf.d mkdir /etc/nginx/sites-enabled Script de démarrage #! /bin/sh 26

### BEGIN INIT INFO # Provides: nginx # Required-Start: $all # Required-Stop: $all # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: starts the nginx web server # Description: starts nginx using start-stop-daemon ### END INIT INFO PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/local/nginx/sbin/nginx PID=/var/run/nginx.pid NAME=nginx DESC=nginx test -x $DAEMON exit 0 # Include nginx defaults if available if [ -f /etc/default/nginx ] ; then. /etc/default/nginx fi set -e case "$1" in start) echo -n "Starting $DESC: " start-stop-daemon --start --quiet --pidfile $PID \ --exec $DAEMON -- $DAEMON_OPTS echo "$NAME." ;; stop) echo -n "Stopping $DESC: " start-stop-daemon --stop --quiet --pidfile $PID \ --exec $DAEMON echo "$NAME." ;; restart force-reload) echo -n "Restarting $DESC: " start-stop-daemon --stop --quiet --pidfile $PID \ --exec $DAEMON sleep 1 start-stop-daemon --start --quiet --pidfile \ /usr/local/nginx/logs/nginx.pid --exec $DAEMON -- $DAEMON_OPTS echo "$NAME." ;; reload) echo -n "Reloading $DESC configuration: " start-stop-daemon --stop --signal HUP --quiet --pidfile $PID \ --exec $DAEMON echo "$NAME." ;; *) N=/etc/init.d/$NAME echo "Usage: $N {start stop restart force-reload}" >&2 exit 1 ;; esac exit 0 27

# On donne les droits au script, on le configure pour le démarrage mv nginx /etc/init.d/ chmod 755 /etc/init.d/nginx /usr/sbin/update-rc.d -f nginx defaults # démarrer PHP-FPM et NGINX /etc/init.d/php5-fpm start /etc/init.d/nginx start 12.2. Mise en place de APC Installation Apt-get install php-apc Vérifier avec un phpinfo() que le module est bien activé. 12.3. Mise en place de Percona Serveur Installation # Les paquets Debian depuis Percona sont signés avec une clé. Ajout de la clé : gpg --keyserver hkp://keys.gnupg.net --recv-keys 1C4CBDCDCD2EFD2A... [some output removed]... gpg: imported: 1 gpg -a --export CD2EFD2A apt-key add - #Ajout des dépôts dans : /etc/apt/sources.list : deb http://repo.percona.com/apt lenny main deb-src http://repo.percona.com/apt lenny main # On fait un update: apt-get update 28

# Installation : apt-get install percona-server-client-5.1 percona-server-server-5.1 perconaserver-common 12.4. Mise en place de la réplication Master/Slave Près Requis Avant de commencer la réplication il faut s assurer que nos 2 serveurs contiennent la même base. Pour cela nous copions le contenu de la base javel du serveur javel vers le serveur ajax. #On crée un dump du master: mysqldump -u root -ppassword -P 3306 -r /root/dump.sql javel #On envoi le dump sur le slave: scp /root/dump.sql root@10.104.3.1:/root Coté Master Editez le fichier my.cnf qui se trouve normalement dans /etc/ : Ajoutez-y les lignes suivantes : [mysqld] log-bin server-id=1 #Relancez le serveur Mysql : /etc/init.d/mysql restart #On se connecte à la base de données du serveur maître. mysql -h 10.105.3.1 -u root -ppassword ou mysql -u root -p (en local) #On crée un utilisateur pour la réplication : GRANT REPLICATION SLAVE ON *.* TO repli@'%' IDENTIFIED BY 'repli'; #On interdit l écriture sur les bases : FLUSH TABLES WITH READ LOCK; 29

#Pour annulé l'interdit: UNLOCK TABLES; #On récupère le nom du fichier binaire, et son offset. Notez les, nous en auront besoin après pour configurer l esclave. SHOW MASTER STATUS; #Noter le nom du fichier dans la colonne File qui doit ressembler normalement à log-bin- et noter aussi le numéro dans "Position". mysql > SHOW MASTER STATUS; +---------------------+------------+---------------------+----------------------- ---+ File Position Binlog_Do_DB Binlog_Ignore_DB +---------------------+------------+---------------------+----------------------- ---+ mysql-bin.003 73 +---------------------+------------+---------------------+----------------------- ---+ 1 row in set (0.06 sec) Coté Slave #On se connecte sur le serveur et on stoppe le serveur MySQL /etc/init.d/mysql stop #Éditez le fichier my.cnf du serveur secondaire et : Ajoutez-y les lignes suivantes : [mysqld] server-id=2 master-host = 10.105.3.1 master-user = repli master-password = repli master-port = 3306 #Relancez le serveur Mysql esclave comme vu plus haut pour le serveur maitre. On se connecte au prompt Mysql : mysql -u root -p #On change les données sur l'esclave, en remplaçant les valeurs entre crochets <> par les valeurs que vous aviez lu sur le maître, ou qui sont valables pour votre système : mysql> CHANGE MASTER TO -> MASTER_HOST='<master host name>', -> MASTER_USER='<replication user name>', -> MASTER_PASSWORD='<replication password>', -> MASTER_LOG_FILE='<recorded log file name>', -> MASTER_LOG_POS=<recorded log offset>; 30

#On démarre l esclave START SLAVE ; #On vérifie si tout s est déroulé correctement SHOW SLAVE STATUS; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.105.3.1 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: ServerA-bin.000001 Read_Master_Log_Pos: 98 Relay_Log_File: ServerB-relay-bin.000002 Relay_Log_Pos: 238 Relay_Master_Log_File: ServerA-bin.000001 Slave_IO_Running: Yes //Les deux thread de l esclave sont actifs Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 98 Relay_Log_Space: 238 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 //si cette valeur est a NULL la repli ne fonctionne pas 1 row in set (0.00 sec) 12.5. Mise en place de mysql cluster L installation de mysql cluster se fait en téléchargeant l'archive mysql cluster dans notre répertoire maison et en l'y désarchivant : tar xvf Téléchargements/mysql-cluster-gpl-7.1.3-linux-x86_64-glibc23.tar.gz ln -s mysql-cluster-gpl-7.1.3-linux-x86_64-glibc23 mysqlc 31

Pour la configuration et pour ce premier cluster, nous commencerons par un seul serveur Mysql (mysqld), une paire de «Data Nodes» (ndbd) et un «Management Node» (ndb_mgmd), le tout fonctionnant sur le même serveur. Création des répertoires de configuration et de données : mkdir my_cluster my_cluster/ndb_data my_cluster/mysqld_data my_cluster/conf Dans le répertoire conf, on crée deux fichiers : my.cnf : [mysqld] ndbcluster datadir=~/my_cluster/mysqld_data basedir=~/mysqlc port=5000 config.ini : [ndb_mgmd] hostname=localhost datadir=~/my_cluster/ndb_data id=1 [ndbd default] noofreplicas=2 datadir=~/my_cluster/ndb_data [ndbd] hostname=localhost id=3 [ndbd] hostname=localhost id=4 [mysqld] id=50 D'autres paramètres existent permettant d'optimiser la configuration. Comme tout serveur Mysql, le processus mysqld nécessite la création une base de données : cd mysqlc scripts/mysql_install_db --no-defaults datadir=$home/my_cluster/mysqld_data/ 32

Résultat habib@habib-live:~/mysqlc$ scripts/mysql_install_db --no-defaults-- datadir=$home/my_cluster/mysqld_data/ Installing MySQL system tables... OK Filling help tables... OK To start mysqld at boot time you have to copy support-files/mysql.server to the right place for your system PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER! To do so, start the server, then issue the following commands:./bin/mysqladmin -u root password 'new-password'./bin/mysqladmin -u root -h habib-live password 'new-password' Alternatively you can run:./bin/mysql_secure_installation which will also give you the option of removing the test databases and anonymous user created by default. This is strongly recommended for production servers. See the manual for more instructions. You can start the MySQL daemon with: cd. ;./bin/mysqld_safe & You can test the MySQL daemon with mysql-test-run.pl cd./mysql-test ; perl mysql-test-run.pl Please report any problems with the./bin/mysqlbug script! On lance les processus selon cet ordre : «management node», «data nodes» et serveur mysql cd../my_cluster/ //On entre dans le repertoire my_cluster $HOME/mysqlc/bin/ndb_mgmd -f conf/config.ini --initial -- configdir=$home/my_cluster/conf/ //on lance le «node management» $HOME/mysqlc/bin/ndbd -c localhost:1186 $HOME/mysqlc/bin/ndbd -c localhost:1186 // On lance les «data nodes» Vérification du statut du cluster $HOME/mysqlc/bin/ndb_mgm -e show On obtient : 33

habib@habib-live:~/my_cluster$ $HOME/mysqlc/bin/ndb_mgm -e show Connected to Management Server at: localhost:1186 Cluster Configuration --------------------- [ndbd(ndb)] 2 node(s) id=3 @127.0.0.1 (mysql-5.1.56 ndb-7.1.13, Nodegroup: 0, Master) id=4 @127.0.0.1 (mysql-5.1.56 ndb-7.1.13, Nodegroup: 0) [ndb_mgmd(mgm)] 1 node(s) id=1 @127.0.0.1 (mysql-5.1.56 ndb-7.1.13) [mysqld(api)] 1 node(s) id=50 (not connected, accepting connect from any host) On lance le serveur mysql $HOME/mysqlc/bin/mysqld --defaults-file=conf/my.cnf & Connection au serveur Mysql et confirmation de creation d'une table utilisant le moteur de stockage ndb propre à Mysql Cluster $HOME/mysqlc/bin/mysql -h 127.0.0.1 -P 5000 -u root create database clusterdb;use clusterdb; create table simples (id int not null primary key) engine=ndb; insert into simples values (1),(2),(3),(4); select * from simples; mysql> create table simples (id int not null primary key) engine=ndb; 110523 8:38:44 [Note] NDB Binlog: CREATE TABLE Event: REPL$clusterdb/simples Query OK, 0 rows affected (0.25 sec) mysql> insert into simples values (1),(2),(3),(4); Query OK, 4 rows affected (0.09 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql> select * from simples; +----+ id +----+ 3 1 2 4 +----+ 4 rows in set (0.07 sec) Pour se déconnecter, on arrête d'abord le serveur mysql puis les autres noeuds du cluster via l'outil ndb_mgm $HOME/mysqlc/bin/mysqladmin -u root -h 127.0.0.1 -P 5000 shutdown $HOME/mysqlc/bin/ndb_mgm -e shutdown 34