fermer
Technologies

Comment optimiser votre serveur ? Différents principes sont abordés !

WhatsApp : La transcription des messages vocaux arrive enfin !

Voici cinq règles pour vous aider à optimiser votre installation de WordPress, ainsi que quelques exemples pour illustrer comment les appliquer. L’optimisation des serveurs est un vaste domaine, et il est en constante évolution, mais nous pouvons étudier les cas simples à comprendre.

Dans cet article, nous allons nous concentrer sur un petit nombre de variables et mesurer leur impact sur les performances.

Vous ne pouvez pas optimiser sans effectuer une analyse comparative

Il existe différents outils dont vous avez besoin pour faire une évaluation correcte, mais pour cet article nous allons nous concentrer sur le plus important : Benchmark Apache. Utilisez cet outil pour interroger des pages spécifiques sur votre site Web (vous pouvez même lui passer des informations pour simuler un cookie authentifié) et obtenir le temps réponse. Vous pouvez utiliser le Benchmark Apache en ligne de commande sur le serveur que vous testez et ainsi obtenir des résultats valables, car il a une trace entre le CPU et la RAM.

Voici une utilisation typique :

[sourcecode language= »bash »]
$ ab -n 1000 -c 20 http://exemple.fr/
[/sourcecode]

Les valeurs définies dans cette ligne de commande sont :

  • n : nombre de demandes de page
  • c : connexions simultanées

Le paramètre le plus important est c, le nombre de requêtes simultanées, tandis que n est un nombre qui doit être assez grand pour fournir des résultats stables. L’astuce consiste à tester le site avec diverses valeurs de c, en commençant par un petit nombre et l’augmenter jusqu’à ce que la valeur retournée de « requêtes par seconde » commence à diminuer. Voici un exemple :

[sourcecode language= »bash »]
$ ab -n 1000 -c 5 http://exemple.fr/ | grep ‘Requests per second’
Requests per second: 723.52 [#/sec] (mean)
$ ab -n 1000 -c 10 http://exemple.fr/ | grep ‘Requests per second’
Requests per second: 690.98 [#/sec] (mean)
$ ab -n 1000 -c 15 http://exemple.fr/ | grep ‘Requests per second’
Requests per second: 700.79 [#/sec] (mean)
$ ab -n 1000 -c 20 http://exemple.fr/ | grep ‘Requests per second’
Requests per second: 710.12 [#/sec] (mean)
[/sourcecode]

On peut affiner la valeur de c en l’incrémentant petit à petit.

Réduire l’empreinte mémoire jusqu’à la fin de la page

La raison la plus probable pour laquelle les requêtes par seconde (requests per second) chutent brusquement, est parce que nous surchargeons la mémoire et le système commence à swapper en mémoire virtuelle paging file. Il s’agit d’un fichier qui, en quelque sorte joue le rôle de chasseur virtuel. Lorsque la charge imposée approche le point de saturation de la mémoire vive installée, le système tente d’en obtenir davantage et se met en quête d’un substitut en sollicitant le fichier de chasse (paging file), c’est-à-dire la mémoire virtuelle.
Cela a les mêmes effets sur la performance globale que lors de l’ouverture de trop d’applications sur Windows, Mac OS X, ou tout autre système prenant en charge le paging.

Après avoir lancé votre benchmark, jetez un œil à la façon dont le fichier d’échange (swap file) est utilisé. Voici des valeurs sur un serveur de 4Go de RAM :

[sourcecode language= »bash »]
$ free -m
total used free shared buffers cached
Mem: 3949 3811 138 0 267 1867
-/+ buffers/cache: 1676 2272
Swap: 2047 16 2031

[/sourcecode]

Ici on utilise seulement 16 Mo du fichier d’échange (swap file). En revanche, dès que l’on augmente le nombre de connexions simultanées (c), on peut monter très rapidement la valeur du fichier d’échange. En clair, ce que vous devez faire en premier lieu, c’est ramener la valeur au plus proche de zéro :

[sourcecode language= »bash »]
$ sudo swapoff -a
$ sudo swapon -a
$ free -m
total used free shared buffers cached
Mem: 3949 3792 157 0 267 1882
-/+ buffers/cache: 1643 2306
Swap: 2047 0 2047
[/sourcecode]

Maintenant, le but est de refaire le test ci-dessus avec les valeurs de c qui sont proches de celui où nous voyons une baisse de performance, et vérifier le fichier d’échange, après chaque demande :

[sourcecode language= »bash »]
$ ab -n 1000 -c 5 http://exemple.fr/ | grep ‘Requests per second’
Requests per second: 723.18 [#/sec] (mean)
Swap: 2047 0 2047
$ ab -n 1000 -c 10 http://exemple.fr/ | grep ‘Requests per second’
Requests per second: 700.79 [#/sec] (mean)
Swap: 2047 192 2047
$ ab -n 1000 -c 15 http://exemple.fr/ | grep ‘Requests per second’
Requests per second: 643.68 [#/sec] (mean)
Swap: 2047 271 2047
[/sourcecode]

Comme vous pouvez le voir dans les résultats ci-dessus, le taux des requêtes commence à diminuer de façon significative lorsque le serveur commence à swapper avec environ 40 connexions simultanées.

Attention aux nombres de connexions…

Par défaut, Apache et MySQL sont configurés pour accepter 150 connexions. La plupart des applications PHP tels que WordPress, autorisent seulement une connexion par thread, vous pouvez donc, sans risque, définir le nombre de connexions des deux services avec la même valeur.

Note : Sachez que MySQL permet de gérer n+1 connexions, vous permettant d’avoir une connexion supplémentaire disponible en cas de gestion du serveur de base de données.

Malheureusement, dans la tentative « d’optimiser » un serveur, certains administrateurs de serveur pourront augmenter le nombre de connexions à 500, 10000, voir plus… Mais l’effet obtenu est catastrophique, dès lors que le serveur monte en charge (load average).

Des sites comme WordPress ne nécessitent généralement pas plus de 32 Mo de RAM par requête, et vous pouvez observer la valeur moyenne en regardant les résultats retournés par la commande top :

[sourcecode language= »bash »]
$ top
top – 11:07:05 up 362 days, 12:30, 1 user, load average: 1.30, 0.95, 0.72
Tasks: 138 total, 4 running, 134 sleeping, 0 stopped, 0 zombie
Cpu(s): 9.4%us, 1.6%sy, 0.0%ni, 87.0%id, 2.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 4044516k total, 3921728k used, 122788k free, 273236k buffers
Swap: 2097144k total, 17204k used, 2079940k free, 1901392k cached

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1320 wwwrun 16 0 309m 40m 20m R 7 1.0 0:02.35 httpd2-prefork
2274 wwwrun 16 0 296m 28m 20m S 6 0.7 0:00.96 httpd2-prefork
596 wwwrun 16 0 296m 32m 24m S 5 0.8 0:05.56 httpd2-prefork
2260 wwwrun 15 0 296m 28m 20m S 4 0.7 0:00.88 httpd2-prefork
6686 mysql 15 0 2300m 1.1g 5664 S 4 27.6 3521:32 mysqld
2279 wwwrun 16 0 296m 23m 16m S 3 0.6 0:00.45 httpd2-prefork
1755 wwwrun 17 0 296m 28m 20m S 3 0.7 0:02.46 httpd2-prefork
2273 wwwrun 16 0 312m 39m 16m S 3 1.0 0:00.71 httpd2-prefork
1959 wwwrun 16 0 296m 23m 15m S 3 0.6 0:00.53 httpd2-prefork
1967 wwwrun 17 0 296m 23m 15m S 3 0.6 0:00.31 httpd2-prefork
2243 wwwrun 16 0 296m 21m 14m S 3 0.5 0:00.24 httpd2-prefork
1197 wwwrun 16 0 307m 36m 17m R 2 0.9 0:01.76 httpd2-prefork
[/sourcecode]

L’astuce consiste à estimer la quantité de mémoire utilisée par Apache, en faisant la moyenne des valeurs de la colonne « RES » (The non-swapped physical memory a task has used) utilisées par les processus. Dans notre exemple la valeur moyenne des « RES » est d’environ 29 Mo.

Vous devez aussi regarder la somme de la mémoire libre lorsque le serveur n’est pas sous la charge du processus httpd2.

[sourcecode language= »bash »]
$ top
top – 07:22:33 up 363 days, 8:45, 1 user, load average: 0.13, 0.22, 0.11
Tasks: 99 total, 1 running, 98 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.1%us, 0.1%sy, 0.0%ni, 99.4%id, 0.4%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 4044516k total, 3768664k used, 275852k free, 341132k buffers
Swap: 2097144k total, 0k used, 2097144k free, 1839256k cached

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 16 0 796 296 244 S 0 0.0 0:14.55 init
2 root RT 0 0 0 0 S 0 0.0 0:01.34 migration/0
3 root 34 19 0 0 0 S 0 0.0 0:00.46 ksoftirqd/0
4 root RT 0 0 0 0 S 0 0.0 0:00.60 migration/1
5 root 34 19 0 0 0 S 0 0.0 0:00.28 ksoftirqd/1
6 root RT 0 0 0 0 S 0 0.0 0:00.36 migration/2
7 root 34 19 0 0 0 S 0 0.0 0:00.40 ksoftirqd/2
8 root RT 0 0 0 0 S 0 0.0 0:00.64 migration/3
9 root 34 19 0 0 0 S 0 0.0 0:00.30 ksoftirqd/3
10 root 10 -5 0 0 0 S 0 0.0 0:00.06 events/0
11 root 10 -5 0 0 0 S 0 0.0 0:00.00 events/1
12 root 10 -5 0 0 0 S 0 0.0 0:00.00 events/2
13 root 10 -5 0 0 0 S 0 0.0 0:00.01 events/3
[/sourcecode]

Ici, la quantité de mémoire libre disponible est de 275852Ko, soit 269Mo.

Maintenant, pour confirmer la valeur c constatée ci-dessus, on utilise la formule suivante :

[sourcecode language= »bash »]
c = FREE / RES
c = 269 Mo / 29 Mo
c = 9 #proche de la valeur que nous avions trouvée précédemment
[/sourcecode]

Cette valeur est le seuil où le serveur commence à s’effondrer. Il est indispensable d’éviter qu’Apache effondre le serveur. Pour cela, nous pouvons réduire le nombre de clients de 150 à 9 pour observer l’impact sur la performance.

Pour Apache, éditez le fichier de configuration (dans mon cas c’est /etc/apache2/httpd.conf) et ajustez cette valeur:

[sourcecode language= »bash »]
MaxClients 150
[/sourcecode]

Pour MySQL, ajustez cette valeur :

[sourcecode language= »bash »]
max_connections = 150
[/sourcecode]

Une fois que vous avez modifié ces valeurs avec le résultat obtenu ci-dessus (dans notre cas nous allons utiliser 9), relancer votre benchmark :

[sourcecode language= »bash »]
$ ab -n 1000 -c 5 http://exemple.fr/ | grep ‘Requests per second’
Requests per second: 723.18 [#/sec] (mean)
Swap: 2047 0 2047
$ ab -n 1000 -c 10 http://exemple.fr/ | grep ‘Requests per second’
Requests per second: 700.79 [#/sec] (mean)
Swap: 2047 0 2047
$ ab -n 1000 -c 15 http://exemple.fr/ | grep ‘Requests per second’
Requests per second: 643.68 [#/sec] (mean)
Swap: 2047 0 2047
[/sourcecode]

Comme vous pouvez le voir, le paging est éliminé. Mais pourquoi sommes-nous capables de répondre à plus de quarante demandes concurrentes ? Simplement parce qu’Apache met les requêtes supplémentaires dans une file d’attente, et ne traite seulement que quarante demandes en même temps.
De fait, la réponse au client sera toujours retardée, mais chaque demande est traitée à la seconde évitant ainsi de surcharger la mémoire.

MySQL = RAM

Évidemment, les résultats ci-dessus supposent que votre serveur de base de données soit correctement configuré et que nous n’ayons pas de slow queries. En fait, MySQL n’est généralement pas consommateur de ressources CPU pour les sites comme WordPress. Sur un serveur bien configuré, MySQL ne consomme que 10 à 25% du CPU.

En dehors de la recherche, les requêtes sont très redondantes, et on tire profit des avantages de MySQL qui sont l’optimisation du cache et des fils d’exécution (threads). Il n’est pas rare de voir MySQL configuré pour utiliser près de 50% de la RAM disponible.

Bien entendu, ces chiffres dépendent de la demande. La règle est de donner à MySQL autant de RAM que possible.

Apache = CPU

Sur les sites comme WordPress, Apache passe la majorité de son temps à exécuter du code PHP. En fait, un bon indicateur de l’optimisation des serveurs, c’est quand Apache utilise 100% du CPU disponible.

Parce que, si vous permettez à Apache de répondre à un trop grand nombre de requêtes concourantes, le taux de requêtes par seconde ne fera qu’augmenter !

Conclusion

Dans cet article je viens de décrire certains aspects de l’optimisation des serveurs. Nous avons dû faire plusieurs hypothèses pour y arriver, mais j’espère que les points étaient clairs, et qu’ils vous aideront à faire de meilleurs choix lors de vos futurs déploiements.

Avez-vous déjà été confronté à des problèmes d’optimisation ? Si c’est le cas, pouvez-vous venir en parler dans les commentaires. Il serait intéressant de comparer nos points de vue mais également les différentes solutions que l’on peut y apporter.

Tags : apacheCPUeffondrementMySQLoptimisationperformancesPHPRAMrequêtesserveurtop
Yohann Poiron

The author Yohann Poiron

J’ai fondé le BlogNT en 2010. Autodidacte en matière de développement de sites en PHP, j’ai toujours poussé ma curiosité sur les sujets et les actualités du Web. Je suis actuellement engagé en tant qu’architecte interopérabilité.