blob: 55db19487a78f6431af0a14904b28a364414ba07 [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr"><head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<!--
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
This file is generated from xml source: DO NOT EDIT
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-->
<title>Amélioration des performances - Serveur HTTP Apache Version 2.5</title>
<link href="../style/css/manual.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet" />
<link href="../style/css/manual-loose-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size" />
<link href="../style/css/manual-print.css" rel="stylesheet" media="print" type="text/css" /><link rel="stylesheet" type="text/css" href="../style/css/prettify.css" />
<script src="../style/scripts/prettify.min.js" type="text/javascript">
</script>
<link href="../images/favicon.ico" rel="shortcut icon" /></head>
<body id="manual-page"><div id="page-header">
<p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/quickreference.html">Directives</a> | <a href="http://wiki.apache.org/httpd/FAQ">FAQ</a> | <a href="../glossary.html">Glossaire</a> | <a href="../sitemap.html">Plan du site</a></p>
<p class="apache">Serveur HTTP Apache Version 2.5</p>
<img alt="" src="../images/feather.png" /></div>
<div class="up"><a href="./"><img title="&lt;-" alt="&lt;-" src="../images/left.gif" /></a></div>
<div id="path">
<a href="http://www.apache.org/">Apache</a> &gt; <a href="http://httpd.apache.org/">Serveur HTTP</a> &gt; <a href="http://httpd.apache.org/docs/">Documentation</a> &gt; <a href="../">Version 2.5</a> &gt; <a href="./">Documentations diverses</a></div><div id="page-content"><div id="preamble"><h1>Amélioration des performances</h1>
<div class="toplang">
<p><span>Langues Disponibles: </span><a href="../en/misc/perf-scaling.html" hreflang="en" rel="alternate" title="English">&nbsp;en&nbsp;</a> |
<a href="../es/misc/perf-scaling.html" hreflang="es" rel="alternate" title="Español">&nbsp;es&nbsp;</a> |
<a href="../fr/misc/perf-scaling.html" title="Français">&nbsp;fr&nbsp;</a></p>
</div>
<p>Il est dit dans la documentation d'Apache 1.3
à propos de l'amélioration des performances :
</p>
<blockquote><p>
"Apache est un serveur web à vocation générale, conçu pour
être non seulement efficace mais aussi rapide. Dans sa
configuration de base, ses performances sont déjà
relativement satisfaisantes. La plupart des sites possèdent
une bande passante en sortie inférieure à 10 Mbits que le
serveur Apache peut mettre pleinement à profit en utilisant un serveur à base
de processeur Pentium bas de gamme."</p>
</blockquote>
<p>Cette phrase ayant été écrite il y a plusieurs années,
entre temps de nombreuses choses ont changé. D'une part, les
serveurs sont devenus beaucoup plus rapides. D'autre part, de
nombreux sites se voient maintenant allouée une bande passante
en sortie bien supérieure à 10 Mbits. En outre, les applications
web sont devenues beaucoup plus complexes. Les sites classiques
ne proposant que des pages du style brochure sont toujours
présents, mais le web a souvent évolué vers une plateforme
exécutant des traitements, et les webmasters peuvent maintenant
mettre en ligne des contenus dynamiques en Perl, PHP ou Java,
qui exigent un niveau de performances bien supérieur.
</p>
<p>C'est pourquoi en dépit des progrès en matière de bandes passantes
allouées et de rapidité des serveurs, les performances
des serveurs web et des applications web sont toujours un sujet
d'actualité. C'est dans ce cadre que cette documentation s'attache à
présenter de nombreux points concernant les performances des
serveurs web.
</p>
</div>
<div id="quickview"><ul id="toc"><li><img alt="" src="../images/down.gif" /> <a href="#what-will-and-will-not-be-discussed">Ce qui sera abordé et ce qui ne le sera pas</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#monitoring-your-server">Monitoring de votre serveur</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#configuring-for-performance">Configuration dans une optique de performances
</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#caching-content">Mise en cache des contenus
</a></li>
<li><img alt="" src="../images/down.gif" /> <a href="#further-considerations">Pour aller plus loin
</a></li>
</ul><h3>Voir aussi</h3><ul class="seealso"><li><a href="#comments_section">Commentaires</a></li></ul></div>
<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="what-will-and-will-not-be-discussed" id="what-will-and-will-not-be-discussed">Ce qui sera abordé et ce qui ne le sera pas</a> <a title="Lien permanent" href="#what-will-and-will-not-be-discussed" class="permalink">&para;</a></h2>
<p>Ce document se concentre sur l'amélioration des performances
via des options facilement accessibles, ainsi que sur les outils
de monitoring. Les outils de monitoring vous permettront de
surveiller le fonctionnement de votre serveur web afin de
rassembler des informations à propos de ses performances et des
éventuels problèmes qui s'y rapportent. Nous supposerons
que votre budget n'est pas illimité ; c'est pourquoi les
améliorations apportées le seront sans modifier l'infrastructure
matérielle existante. Vous ne souhaitez probablement pas
compiler vous-même votre serveur Apache, ni recompiler le noyau
de votre système d'exploitation ; nous supposerons cependant que
vous possédez quelques notions à propos du fichier de
configuration du serveur HTTP Apache.
</p>
</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="monitoring-your-server" id="monitoring-your-server">Monitoring de votre serveur</a> <a title="Lien permanent" href="#monitoring-your-server" class="permalink">&para;</a></h2>
<p>Si vous envisagez de redimensionner ou d'améliorer les performances
de votre serveur, vous devez tout d'abord observer la manière dont il
fonctionne. En observant son fonctionnement en conditions réelles ou
sous une charge créée artificiellement, vous serez en mesure
d'extrapoler son fonctionnement sous une charge accrue, par exemple dans
le cas où il serait mentionné sur Slashdot. </p>
<h3><a name="monitoring-tools" id="monitoring-tools">Outils de monitoring</a></h3>
<h4><a name="top" id="top">top
</a></h4>
<p>L'outil top est fourni avec Linux et FreeBSD. Solaris
quant à lui, fournit <code>prstat(1)</code>. Cet outil
permet de rassembler de nombreuses données statistiques
à propos du système et de chaque processus en cours
d'exécution avant de les afficher de manière
interactive sur votre terminal. Les données affichées
sont rafraîchies toutes les secondes et varient en
fonction de la plateforme, mais elles comportent en
général la charge moyenne du système, le nombre de
processus et leur état courant, le pourcentage de temps
CPU(s) passé à exécuter le code système et utilisateur,
et l'état de la mémoire virtuelle système. Les données
affichées pour chaque processus sont en général
configurables et comprennent le nom et l'identifiant du
processus, sa priorité et la valeur définie par nice,
l'empreinte mémoire, et le pourcentage d'utilisation CPU.
L'exemple suivant montre plusieurs processus httpd (avec
les MPM worker et event) s'exécutant sur un système
Linux (Xen) :
</p>
<div class="example"><pre>top - 23:10:58 up 71 days, 6:14, 4 users, load average: 0.25, 0.53, 0.47
Tasks: 163 total, 1 running, 162 sleeping, 0 stopped, 0 zombie
Cpu(s): 11.6%us, 0.7%sy, 0.0%ni, 87.3%id, 0.4%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 2621656k total, 2178684k used, 442972k free, 100500k buffers
Swap: 4194296k total, 860584k used, 3333712k free, 1157552k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
16687 example_ 20 0 1200m 547m 179m S 45 21.4 1:09.59 httpd-worker
15195 www 20 0 441m 33m 2468 S 0 1.3 0:41.41 httpd-worker
1 root 20 0 10312 328 308 S 0 0.0 0:33.17 init
2 root 15 -5 0 0 0 S 0 0.0 0:00.00 kthreadd
3 root RT -5 0 0 0 S 0 0.0 0:00.14 migration/0
4 root 15 -5 0 0 0 S 0 0.0 0:04.58 ksoftirqd/0
5 root RT -5 0 0 0 S 0 0.0 4:45.89 watchdog/0
6 root 15 -5 0 0 0 S 0 0.0 1:42.52 events/0
7 root 15 -5 0 0 0 S 0 0.0 0:00.00 khelper
19 root 15 -5 0 0 0 S 0 0.0 0:00.00 xenwatch
20 root 15 -5 0 0 0 S 0 0.0 0:00.00 xenbus
28 root RT -5 0 0 0 S 0 0.0 0:00.14 migration/1
29 root 15 -5 0 0 0 S 0 0.0 0:00.20 ksoftirqd/1
30 root RT -5 0 0 0 S 0 0.0 0:05.96 watchdog/1
31 root 15 -5 0 0 0 S 0 0.0 1:18.35 events/1
32 root RT -5 0 0 0 S 0 0.0 0:00.08 migration/2
33 root 15 -5 0 0 0 S 0 0.0 0:00.18 ksoftirqd/2
34 root RT -5 0 0 0 S 0 0.0 0:06.00 watchdog/2
35 root 15 -5 0 0 0 S 0 0.0 1:08.39 events/2
36 root RT -5 0 0 0 S 0 0.0 0:00.10 migration/3
37 root 15 -5 0 0 0 S 0 0.0 0:00.16 ksoftirqd/3
38 root RT -5 0 0 0 S 0 0.0 0:06.08 watchdog/3
39 root 15 -5 0 0 0 S 0 0.0 1:22.81 events/3
68 root 15 -5 0 0 0 S 0 0.0 0:06.28 kblockd/0
69 root 15 -5 0 0 0 S 0 0.0 0:00.04 kblockd/1
70 root 15 -5 0 0 0 S 0 0.0 0:00.04 kblockd/2</pre></div>
<p>Top est un merveilleux outil, même s'il est
relativement gourmand en ressources (lorsqu'il
s'exécute, son propre processus se trouve en général
dans le top dix des consommations CPU). Il est
indispensable pour déterminer la taille d'un processus
en cours d'exécution, information précieuse lorsque vous
voudrez déterminer combien de processus httpd vous
pourrez exécuter sur votre machine. La méthode pour
effectuer ce calcul est décrite ici : <a href="#sizing-maxClients">calculer MaxClients</a>. Top
est cependant un outil interactif, et l'exécuter de
manière continu présente peu ou pas d'avantage.
</p>
<h4><a name="free" id="free">free
</a></h4>
<p>Cette commande n'est disponible que sous Linux. Elle
indique la mémoire vive et l'espace de swap utilisés.
Linux alloue la mémoire inutilisée en tant que cache du
système de fichiers. La commande free montre
l'utilisation de la mémoire avec et sans ce cache. On
peut utiliser la commande free pour déterminer la
quantité de mémoire utilisée par le système, comme
décrit dans le paragraphe <a href="#sizing-maxClients">calculer MaxClients</a>.
L'affichage de la sortie de la commande free ressemble à
ceci :
</p>
<div class="example"><pre>sctemme@brutus:~$ free
total used free shared buffers cached
Mem: 4026028 3901892 124136 0 253144 841044
-/+ buffers/cache: 2807704 1218324
Swap: 3903784 12540 3891244</pre></div>
<h4><a name="vmstat" id="vmstat">vmstat
</a></h4>
<p>Cette commande est disponible sur de nombreuses
plateformes de style Unix. Elle affiche un grand nombre
de données système. Lancée sans argument, elle affiche
une ligne d'état pour l'instant actuel. Lorsqu'on lui
ajoute un chiffre, la ligne d'état actuelle est ajoutée à
intervalles réguliers à l'affichage existant.
Par exemple, la commande
<code>vmstat 5</code> ajoute la ligne d'état actuelle
toutes les 5 secondes. La commande vmstat affiche la
quantité de mémoire virtuelle utilisée, la quantité de
mémoire échangée avec l'espace de swap en entrée et en
sortie à chaque seconde, le nombre de processus
actuellement en cours d'exécution ou inactifs, le nombre
d'interruptions et de changements de contexte par
seconde, et le pourcentage d'utilisation du CPU.
</p>
<p>
Voici la sortie de la commande <code>vmstat</code>
pour un serveur inactif :
</p>
<div class="example"><pre>[sctemme@GayDeceiver sctemme]$ vmstat 5 3
procs memory swap io system cpu
r b w swpd free buff cache si so bi bo in cs us sy id
0 0 0 0 186252 6688 37516 0 0 12 5 47 311 0 1 99
0 0 0 0 186244 6696 37516 0 0 0 16 41 314 0 0 100
0 0 0 0 186236 6704 37516 0 0 0 9 44 314 0 0 100</pre></div>
<p>Et voici cette même sortie pour un serveur en charge
de cent connexions simultanées pour du contenu statique :
</p>
<div class="example"><pre>[sctemme@GayDeceiver sctemme]$ vmstat 5 3
procs memory swap io system cpu
r b w swpd free buff cache si so bi bo in cs us sy id
1 0 1 0 162580 6848 40056 0 0 11 5 150 324 1 1 98
6 0 1 0 163280 6856 40248 0 0 0 66 6384 1117 42 25 32
11 0 0 0 162780 6864 40436 0 0 0 61 6309 1165 33 28 40</pre></div>
<p>La première ligne indique des valeurs moyennes depuis
le dernier redémarrage. Les lignes suivantes donnent des
informations d'état à intervalles de 5 secondes. Le
second argument demande à vmstat de générer 3 lignes
d'état, puis de s'arrêter.
</p>
<h4><a name="se-toolkit" id="se-toolkit">Boîte à outils SE
</a></h4>
<p>La boîte à outils SE est une solution de supervision
pour Solaris. Son langage de programmation est basé sur
le préprocesseur C et est fourni avec de nombreux
exemples de scripts. Les informations fournies
peuvent être exploitées en mode console ou en mode
graphique. Cette boîte à outils peut aussi être programmée pour
appliquer des règles aux données système. Avec l'exemple
de script de la Figure 2, Zoom.se, des voyants verts,
oranges ou rouges s'allument lorsque certaines valeurs
du système dépassent un seuil spécifié. Un autre script
fourni, Virtual Adrian, permet d'affiner les
performances en tenant compte de ces valeurs.
</p>
<p>Depuis sa création, de nombreux propriétaires se sont
succédés à la tête de la boîte à outils SE, et elle a de
ce fait largement évolué. Il semble qu'elle ait
maintenant trouvé sa place chez Sunfreeware.com d'où
elle peut être téléchargée gratuitement. Il n'y a qu'un
seul paquet pour Solaris 8, 9 et 10 sur SPARC et x86, et
il inclut le code source. Le concepteur de la boîte à
outils SE, Richard Pettit, a fondé une nouvelle sociéte,
Captive Metrics4, et a l'intention de mettre sur le
marché un outil de supervision multiplateforme en Java basé sur
les mêmes principes que la boîte à outils SE.
</p>
<h4><a name="dtrace" id="dtrace">DTrace
</a></h4>
<p>Etant donné que DTrace est disponible sous Solaris,
FreeBSD et OS X, il serait intéressant de l'étudier. Il
y a aussi le module mod_dtrace pour httpd.
</p>
<h4><a name="mod_status" id="mod_status">mod_status
</a></h4>
<p>Le module mod_status donne un aperçu des performances
du serveur à un instant donné. Il génère une page HTML
comportant, entre autres, le nombre de processus Apache
en cours d'exécution avec la quantité de données qu'ils
ont servies, ainsi que la charge CPU induite par httpd
et le reste du système. L'Apache Software Foundation
utilise elle-même <code class="module"><a href="../mod/mod_status.html">mod_status</a></code> pour son
propre <a href="http://apache.org/server-status">site
web</a>. Si vous ajoutez une directive
<code>ExtendedStatus On</code> à votre fichier
<code>httpd.conf</code>, la page de
<code class="module"><a href="../mod/mod_status.html">mod_status</a></code> vous fournira d'avantage
d'informations, au prix d'une consommation de ressources
légèrement supérieure par requête.
</p>
<h3><a name="web-server-log-files" id="web-server-log-files">Les journaux du serveur web
</a></h3>
<p>Le moyen le plus efficace pour vérifier la bonne santé et
le niveau de performance de votre serveur consiste à
surveiller et analyser les journaux écrits par httpd. La
surveillance du journal des erreurs vous permet de
déterminer les sources d'erreurs, de détecter des attaques
ou des problèmes de performance. L'analyse du journal des
accès vous indique le niveau de charge de votre serveur,
quelles sont les ressources les plus populaires, ainsi que
la provenance de vos utilisateurs. Une analyse historique des
données de journalisation peut vous fournir des informations
précieuses quant aux tendances d'utilisation de votre
serveur au cours du temps, ce qui vous permet de prévoir les
périodes où les besoins en performance risquent de dépasser
les capacités du serveur.
</p>
<h4><a name="ErrorLog" id="ErrorLog">Journal des erreurs
</a></h4>
<p>Le journal des erreurs peut indiquer que le nombre
maximum de processus actifs ou de fichiers ouverts
simultanément a été atteint. Le journal des erreurs
signele aussi le lancement de processus supplémentaires selon un
taux supérieur à la normale en réponse à
une augmentation soudaine de la charge. Lorsque le
serveur démarre, le descripteur de fichier stderr est
redirigé vers le journal des erreurs, si bien que toute
erreur rencontrée par httpd après avoir ouvert ses
fichiers journaux apparaîtra dans ce journal. Consulter
fréquemment le journal des erreurs est donc une bonne
habitude.
</p>
<p>Lorsque Apache httpd n'a pas encore ouvert ses
fichiers journaux, tout message d'erreur sera envoyé
vers la sortie d'erreur standard stderr. Si vous
démarrez httpd manuellement, ces messages d'erreur
apparaîtront sur votre terminal, et vous pourrez les
utiliser directement pour résoudre les problèmes de
votre serveur. Si httpd est lancé via un script de
démarrage, la destination de ces messages d'erreur
dépend de leur conception.
<code>/var/log/messages</code> est alors le premier fichier à
consulter. Sous Windows, ces messages d'erreur précoces
sont écrits dans le journal des évènements des
applications, qui peut être visualisé via l'observateur
d'évènements dans les outils d'administration.
</p>
<p>
Le journal des erreurs est configuré via les
directives de configuration <code class="directive"><a href="../mod/core.html#errorlog">ErrorLog</a></code> et <code class="directive"><a href="../mod/core.html#loglevel">LogLevel</a></code>. Le journal des
erreurs de la configuration du serveur principal de
httpd reçoit les messages d'erreur concernant
l'ensemble du serveur : démarrage, arrêt, crashes,
lancement de processus supplémentaires excessif,
etc... La directive <code class="directive"><a href="../mod/core.html#errorlog">ErrorLog</a></code> peut aussi être
utilisée dans les blocs de configuration des
serveurs virtuels. Le journal des erreurs d'un
serveur virtuel ne reçoit que les messages d'erreur
spécifiques à ce serveur virtuel, comme les erreurs
d'authentification et les erreurs du style 'File not
Found'.
</p>
<p>Dans le cas d'un serveur accessible depuis Internet,
attendez-vous à voir de nombreuses tentatives
d'exploitation et attaques de vers dans le journal des
erreurs. La plupart d'entre elles ciblent des serveurs
autres qu'Apache, mais dans l'état actuel des choses,
les scripts se contentent d'envoyer leurs attaques vers
tout port ouvert, sans tenir compte du serveur web
effectivement en cours d'exécution ou du type
des applications installées. Vous pouvez bloquer ces
tentatives d'attaque en utilisant un pare-feu ou le
module <a href="http://www.modsecurity.org/">mod_security</a>,
mais ceci dépasse la portée de cette discussion.
</p>
<p>
La directive <code class="directive"><a href="../mod/core.html#loglevel">LogLevel</a></code> permet de définir
le niveau de détail des messages enregistrés dans
les journaux. Il existe huit niveaux de
journalisation :
</p>
<table>
<tr>
<td>
<p><strong>Niveau</strong></p>
</td>
<td>
<p><strong>Description</strong></p>
</td>
</tr>
<tr>
<td>
<p>emerg</p>
</td>
<td>
<p>Urgence - le système est inutilisable.</p>
</td>
</tr>
<tr>
<td>
<p>alert</p>
</td>
<td>
<p>Une action doit être entreprise
immédiatement.</p>
</td>
</tr>
<tr>
<td>
<p>crit</p>
</td>
<td>
<p>Situations critiques.</p>
</td>
</tr>
<tr>
<td>
<p>error</p>
</td>
<td>
<p>Situations d'erreur.</p>
</td>
</tr>
<tr>
<td>
<p>warn</p>
</td>
<td>
<p>Situations provoquant un avertissement.</p>
</td>
</tr>
<tr>
<td>
<p>notice</p>
</td>
<td>
<p>Evènement normal, mais important.</p>
</td>
</tr>
<tr>
<td>
<p>info</p>
</td>
<td>
<p>Informations.</p>
</td>
</tr>
<tr>
<td>
<p>debug</p>
</td>
<td>
<p>Messages de débogage.</p>
</td>
</tr>
</table>
<p>Le niveau de journalisation par défaut est warn. Un
serveur en production ne doit pas s'exécuter en mode
debug, mais augmenter le niveau de détail dans le
journal des erreurs peut s'avérer utile pour résoudre
certains problèmes. A partir de la
version 2.3.8, la directive <code class="directive"><a href="../mod/core.html#loglevel">LogLevel</a></code> peut être définie au
niveau de chaque module :
</p>
<pre class="prettyprint lang-config">LogLevel debug mod_ssl:warn</pre>
<p>
Dans cet exemple, l'ensemble du serveur est en mode
debug, sauf le module <code class="module"><a href="../mod/mod_ssl.html">mod_ssl</a></code>
qui a tendance à être très bavard.
</p>
<h4><a name="AccessLog" id="AccessLog">Journal des accès
</a></h4>
<p>Apache httpd garde la trace de toutes les requêtes
qu'il reçoit dans son journal des accès. En plus de
l'heure et de la nature d'une requête, httpd peut
enregistrer l'adresse IP du client, la date et l'heure
de la requête, le résultat et quantité d'autres
informations. Les différents formats de journaux sont
documentés dans le manuel. Le fichier concerne par
défaut le serveur principal, mais il peut être configuré
pour chaque serveur virtuel via les directives de
configuration <code class="directive"><a href="../mod/mod_log_config.html#transferlog">TransferLog</a></code> ou
<code class="directive"><a href="../mod/mod_log_config.html#customlog">CustomLog</a></code>.
</p>
<p>De nombreux programmes libres ou commerciaux
permettent d'analyser les journaux d'accès. Analog et
Webalyser sont des programmes d'analyse libres parmi les
plus populaires. L'analyse des journaux doit s'effectuer
hors ligne afin de ne pas surcharger le serveur web avec
le traitement des fichiers journaux. La plupart des
programmes d'analyse des journaux sont compatibles avec le format
de journal "Common". Voici une description des
différents champs présents dans une entrée du journal :
</p>
<div class="example"><pre>195.54.228.42 - - [24/Mar/2007:23:05:11 -0400] "GET /sander/feed/ HTTP/1.1" 200 9747
64.34.165.214 - - [24/Mar/2007:23:10:11 -0400] "GET /sander/feed/atom HTTP/1.1" 200 9068
60.28.164.72 - - [24/Mar/2007:23:11:41 -0400] "GET / HTTP/1.0" 200 618
85.140.155.56 - - [24/Mar/2007:23:14:12 -0400] "GET /sander/2006/09/27/44/ HTTP/1.1" 200 14172
85.140.155.56 - - [24/Mar/2007:23:14:15 -0400] "GET /sander/2006/09/21/gore-tax-pollution/ HTTP/1.1" 200 15147
74.6.72.187 - - [24/Mar/2007:23:18:11 -0400] "GET /sander/2006/09/27/44/ HTTP/1.0" 200 14172
74.6.72.229 - - [24/Mar/2007:23:24:22 -0400] "GET /sander/2006/11/21/os-java/ HTTP/1.0" 200 13457</pre></div>
<table>
<tr>
<td>
<p><strong>Champ</strong></p>
</td>
<td>
<p><strong>Contenu</strong></p>
</td>
<td>
<p><strong>Explication</strong></p>
</td>
</tr>
<tr>
<td>
<p>Adresse IP client</p>
</td>
<td>
<p>195.54.228.42</p>
</td>
<td>
<p>Adresse IP d'où provient la requête</p>
</td>
</tr>
<tr>
<td>
<p>Identité RFC 1413</p>
</td>
<td>
<p>-</p>
</td>
<td>
<p>Identité de l'utilisateur distant renvoyée
par son démon identd</p>
</td>
</tr>
<tr>
<td>
<p>Nom utilisateur</p>
</td>
<td>
<p>-</p>
</td>
<td>
<p>Nom de l'utilisateur distant issu de
l'authentification Apache</p>
</td>
</tr>
<tr>
<td>
<p>Horodatage</p>
</td>
<td>
<p>[24/Mar/2007:23:05:11 -0400]</p>
</td>
<td>
<p>Date et heure de la requête</p>
</td>
</tr>
<tr>
<td>
<p>Requête</p>
</td>
<td>
<p>"GET /sander/feed/ HTTP/1.1"</p>
</td>
<td>
<p>La requête proprement dite</p>
</td>
</tr>
<tr>
<td>
<p>Code d'état</p>
</td>
<td>
<p>200</p>
</td>
<td>
<p>Code d'état renvoyé avec la réponse</p>
</td>
</tr>
<tr>
<td>
<p>Contenu en octets</p>
</td>
<td>
<p>9747</p>
</td>
<td>
<p>Total des octets transférés sans les
en-têtes</p>
</td>
</tr>
</table>
<h4><a name="rotating-log-files" id="rotating-log-files">Rotation des fichiers journaux
</a></h4>
<p>Il y a de nombreuses raisons pour mettre en oeuvre la
rotation des fichiers journaux. Même si pratiquement
plus aucun système d'exploitation n'impose une limite de
taille pour les fichiers de deux GigaOctets, avec le
temps, les fichiers journaux deviennent trop gros pour
pouvoir être traités. En outre, toute analyse de journal
ne doit pas être effectuée sur un fichier dans lequel le
serveur est en train d'écrire. Une rotation périodique
des fichiers journaux permet de faciliter leur analyse,
et de se faire une idée plus précise des habitudes
d'utilisation.
</p>
<p>Sur les systèmes unix, vous pouvez simplement
effectuer cette rotation en changeant le nom du fichier
journal via la commande mv. Le serveur continuera à
écrire dans le fichier ouvert même s'il a changé de nom.
Lorsque vous enverrez un signal de redémarrage
"Graceful" au serveur, il ouvrira un nouveau fichier
journal avec le nom configuré par défaut. Par exemple,
vous pouvez écrire un script de ce style pour cron :
</p>
<div class="example"><p><code>
APACHE=/usr/local/apache2<br />
HTTPD=$APACHE/bin/httpd<br />
mv $APACHE/logs/access_log
$APACHE/logarchive/access_log-`date +%F`<br />
$HTTPD -k graceful
</code></p></div>
<p>Cette approche fonctionne aussi sous Windows, mais
avec moins de souplesse. Alors que le processus httpd de
votre serveur sous Windows continuera à écrire dans le
fichier journal une fois ce dernier renommé, le service
Windows qui exécute Apache n'est pas en mesure
d'effectuer un redémarrage graceful. Sous Windows, le
redémarrage d'un service consiste simplement à l'arrêter
et à le démarrer à nouveau, alors qu'avec un redémarrage
graceful, les processus enfants terminent
le traitement des requêtes en cours avant de s'arrêter,
et le serveur httpd est alors immédiatement à
nouveau disponible pour traiter les nouvelles requêtes.
Sous Windows, le processus d'arrêt/redémarrage du
service interrompt les traitements de requêtes en cours,
et le serveur demeure indisponible jusqu'à ce qu'il ait
terminé son redémarrage. Vous devez donc tenir compte de
toutes ces contraintes lorsque vous planifiez un
redémarrage.
</p>
<p>
Une seconde approche consiste à utiliser la
redirection des logs. Les directives <code class="directive"><a href="../mod/mod_log_config.html#customlog">CustomLog</a></code>,
<code class="directive"><a href="../mod/mod_log_config.html#transferlog">TransferLog</a></code> ou
<code class="directive"><a href="../mod/core.html#errorlog">ErrorLog</a></code>
permettent de rediriger les données de journalisation
vers tout programme via le caractère pipe
(<code>|</code>) comme dans cet exemple :
</p>
<div class="example"><p><code>CustomLog "|/usr/local/apache2/bin/rotatelogs
/var/log/access_log 86400" common
</code></p></div>
<p>Le programme cible de la redirection recevra alors les
données de journalisation d'Apache sur son entrée
standard stdin, et pourra en faire ce qu'il voudra. Le
programme rotatelogs fourni avec Apache effectue une
rotation des journaux de manière transparente en
fonction du temps ou de la quantité de données écrites,
et archive l'ancien fichier journal en ajoutant un
suffixe d'horodatage à son nom. Cependant, si cette
méthode fonctionne de manière satisfaisante sur les
plateformes de style unix, il n'en est pas de même sous
Windows.
</p>
<h4><a name="logging-and-performance" id="logging-and-performance">Journalisation et performances
</a></h4>
<p>L'écriture d'entrées dans les fichiers journaux est
consommatrice de ressources, mais l'importance de ces
données est telle qu'il est fortement déconseillé de
désactiver la journalisation. Pour optimiser les
performances, vous devez enregistrer vos journaux sur un
disque physique différent de celui où se situe votre
site web car les modes d'accès sont très différents. La
lecture de données sur un disque possède un caractère
essentiellement aléatoire, alors que l'écriture dans les
fichiers journaux s'effectue de manière séquentielle.
</p>
<p>
Ne définissez jamais la directive <code class="directive"><a href="../mod/core.html#loglevel">LogLevel</a></code> à debug pour un
serveur en production. En effet, lorsque ce niveau de
journalisation est défini, une grande quantité de
données est écrite dans le journal des erreurs, y
compris, dans le cas d'un accès SSL, toutes les
opérations de lecture/écriture de la négociation de la
connexion. Les implications en matière de performances
sont donc importantes et vous devez plutôt utiliser le
niveau de journalisation warn.
</p>
<p>Si votre serveur possède plus d'un serveur virtuel,
il est conseillé d'attribuer un journal des accès séparé à
chacun d'entre eux, ce qui a pour effet de faciliter son
exploitation ultérieure. Par contre, si votre serveur
possède un grand nombre de serveurs virtuels, le nombre
de fichiers journaux à ouvrir va représenter une
consommation de ressources importante pour votre
système, et il sera peut-être alors plus judicieux
d'utiliser un seul fichier journal avec l'aménagement
suivant : utiliser l'élément de format <code>%v</code>
en tête de votre directive <code class="directive"><a href="../mod/mod_log_config.html#logformat">LogFormat</a></code> (et de
votre directive <code class="directive"><a href="../mod/core.html#errorlog">ErrorLog</a></code> depuis la version
2.3.8) afin que httpd enregistre le nom du serveur
virtuel qui traite la requête ou l'erreur au début de
chaque entrée du journal. Un simple script Perl peut
alors éclater le journal en fichiers spécifiques à
chaque serveur virtuel après sa rotation ; Apache
fournit un tel script dans le répertoire
<code>support/split-logfile</code>.
</p>
<p>
Vous pouvez aussi utiliser la directive <code class="directive"><a href="../mod/mod_log_config.html#bufferedlogs">BufferedLogs</a></code>
pour qu'Apache conserve en mémoire plusieurs entrées
de journal avant de les écrire sur disque. Gardez
cependant à l'esprit que si les performances peuvent
s'en trouver améliorées, la chronologie des
évènements enregistrés peut quant à elle s'en
trouver affectée.
</p>
<h3><a name="generating-a-test-load" id="generating-a-test-load">Mise en oeuvre d'une charge de test
</a></h3>
<p>Il est interessant de mettre en oeuvre une charge de test
afin d'évaluer les performances du système en conditions
réelles de fonctionnement. A cet effet, il existe des
paquets commerciaux comme <a href="http://learnloadrunner.com/">LoadRunner</a>, mais
aussi de nombreux outils libres permettant de générer une
charge de test pour votre serveur web.
</p>
<ul>
<li>Apache est fourni avec un programme de test nommé ab
(initiales de Apache Bench). Ce dernier peut générer une
charge de serveur web consistant à demander le même
fichier de manière répétitive à un rythme rapide. Vous
pouvez spécifier le nombre de connexions simultanées, et
choisir entre une durée de fonctionnement ou un nombre
de requêtes.
</li>
<li>http load11 est un autre exemple de générateur de
charge libre. Ce programme fonctionne avec un ficher
d'URLs et peut être compilé avec le support SSL.
</li>
<li>L'Apache Software Foundation propose un outil nommé
flood12. Flood est un programme assez sophistiqué que
l'on configure via un fichier XML.
</li>
<li>Pour finir, JMeter13, un sous-projet de Jakarta, est
un outil de test en charge entièrement en Java. Alors
que les premières versions de cette application étaient
lentes et difficiles d'utilisation, la version 2.1.1
actuelle semble être plus souple d'utilisation et
efficace.
</li>
<li>
<p>Des projets externes à l'ASF et réputés
relativement corrects : grinder, httperf, tsung, <a href="http://funkload.nuxeo.org/">FunkLoad</a>.
</p>
</li>
</ul>
<p>Lorsque vous appliquez une charge de test à votre serveur
web, gardez à l'esprit que si ce dernier est en production,
la charge de test peut en affecter négativement les
performances. En outre, le transfert de données
supplémentaires induit peut être comptabilisé dans le
quota mensuel qui vous a été éventuellement alloué.
</p>
</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="configuring-for-performance" id="configuring-for-performance">Configuration dans une optique de performances
</a> <a title="Lien permanent" href="#configuring-for-performance" class="permalink">&para;</a></h2>
<h3><a name="apache-configuration" id="apache-configuration">Configuration de httpd
</a></h3>
<p>httpd version 2.2 est par défaut un serveur web avec des
processus enfants lancés au préalable. Au démarrage du
serveur, le processus parent lance un certain nombre de
processus enfants et ce sont eux qui seront chargés de traiter les
requêtes. Mais avec httpd version 2.0 est apparu le concept
de module multi-process (MPM). Les développeurs purent alors
écrire des MPMs qui pouvaient fonctionner avec l'architecture
à base de processus ou de threads de leur système
d'exploitation spécifique. Apache 2 est fourni avec des MPMs
spécifiques pour Windows, OS/2, Netware et BeOS. Pour les
plateformes de style unix, les deux MPMS les plus connus
sont Prefork et Worker. Le MPM Prefork offre le même modèle
de processus enfants prélancés que celui d'Apache 1.3. Le
MPM Worker quant à lui, lance un nombre de processus enfants
moins important, mais attribue à chacun d'entre eux un
certain nombre de threads pour traiter les requêtes. Avec la
version 2.4, le MPM n'est plus défini à la compilation,
mais peut être chargé à l'exécution via la directive
<code class="directive"><a href="../mod/core.html#loadmodule">LoadModule</a></code>. Le MPM par
défaut pour la version 2.4 est le MPM event.
</p>
<p>Le nombre maximum de process, à savoir le nombre de processus
enfants prélancés et/ou de threads, donne une approximation
du nombre de requêtes que votre serveur peut traiter
simultanément. Ce n'est cependant qu'une estimation car le
noyau peut mettre en file d'attente des tentatives de
connexion à votre serveur. Lorsque votre site approche de la
saturation et si le nombre maximum de process est atteint, la
machine n'impose pas de limite absolue au
delà de laquelle les clients se verront refuser l'accès.
Cependant, lorsque les requêtes commencent à être mises en
file d'attente, les performances du système se dégradent
rapidement.
</p>
<p>Enfin, si le serveur httpd en question n'exécute aucun
code tiers via <code>mod_php</code>, <code>mod_perl</code>,
etc..., nous recommandons l'utilisation de
<code class="module">mpm_event</code>. Ce MPM est idéal pour les
situations où httpd sert d'intermédiaire entre les clients
et des serveurs d'arrière-plan qui accomplissent le travail
proprement dit (par exemple en mode mandataire ou cache).
</p>
<h4><a name="MaxClients" id="MaxClients">MaxClients
</a></h4>
<p>La directive <code>MaxClients</code> permet de
spécifier le nombre maximum de process que votre serveur
pourra créer. Deux autres directives lui sont associées
: <code>MinSpareServers</code> et
<code>MaxSpareServers</code>, qui permettent d'encadrer
le nombre de process que httpd garde en réserve pour
traiter les requêtes. Le nombre total de process que
httpd peut créer peut
être défini via la directive <code>ServerLimit</code>.
</p>
<h4><a name="spinning-threads" id="spinning-threads">Rotation des threads
</a></h4>
<p>Les directives ci-dessus suffisent pour définir les
limites des nombres de process dans le cas du MPM Prefork.
Cependant, si vous utilisez un MPM à base de threads, la
situation est un peu plus compliquée. Les MPMs à base de
threads supportent la directive
<code>ThreadsPerChild</code>. httpd impose le fait que
<code>MaxClients</code> doit être divisible par
<code>ThreadsPerChild</code>. Si les valeurs que vous
attribuez à ces deux directives ne respectent pas cette
règle, httpd affichera un message d'erreur et corrigera
la valeur de la directive <code>ThreadsPerChild</code>
en la diminuant jusqu'à ce que la valeur de la directive
<code>MaxClients</code> soit divisible par elle.
</p>
<h4><a name="sizing-maxClients" id="sizing-maxClients">Choix de la valeur de MaxClients
</a></h4>
<p>Idéalement, le nombre maximum de processus devrait
être choisi de façon à ce que toute la mémoire système
soit utilisée, sans la dépasser. En effet, si votre
système est surchargé au point de devoir faire appel de
manière intensive au swap (utilisation de la mémoire
disque), les performances vont se dégrader rapidement.
La formule permettant de déterminer la valeur de
<code class="directive"><a href="../mod/mpm_common.html#maxrequestworkers">MaxClients</a></code>
est assez simple :
</p>
<div class="example"><p><code>
MaxClients = (RAM totale − RAM système − RAM pour
les programmes externes) divisé par la RAM nécessaire pour
chaque processus enfant.
</code></p></div>
<p>L'observation est la meilleure manière de déterminer
les différentes quantités de mémoire allouées au
système, aux programmes externes et aux processus httpd
: à cet effet, vous pouvez utiliser les commandes top et
free décrites plus haut pour étudier l'empreinte mémoire
du système lorsque le serveur web n'est pas en cours
d'exécution. Vous pouvez aussi étudier l'empreinte d'un
processus type du serveur web via la commande top ; en
effet, la plupart des implémentations de cette commande
présentent une colonne Mémoire résidente (RSS - Resident
Size) et Mémoire partagée (Shared Memory).
</p>
<p>La différence entre ces deux colonnes est la
quantité de mémoire par processus. Le segment de mémoire
partagée n'existe effectivement qu'une seule fois, et
est utilisé par le code et les bibliothèques chargées et
la concurrence inter-processus (ou tableau de résultat -
scoreboard) géré par Apache. La quantité de mémoire
utilisée par chaque processus dépend fortement du nombre
et du type de modules utilisés. La meilleure façon d'en
déterminer les besoins consiste à générer une charge
type pour votre site web et à observer l'importance que
prennent les processus httpd.
</p>
<p>La RAM pour les programmes externes comprend
principalement la mémoire utilisée pour les programmes
CGI et les scripts qui s'exécutent indépendamment des
processus httpd. Par contre, si vous utilisez une
machine virtuelle Java qui exécute Tomcat sur le même
serveur, cette dernière va aussi nécessiter une quantité
de mémoire significative. En conséquence, la formule
ci-dessus qui sert à calculer la valeur maximale de
<code>MaxClients</code> permet d'effectuer une première approche,
mais ne constitue en aucun cas une science exacte. En
cas de doute, soyez pragmatique et utilisez une valeur assez
basse pour <code>MaxClients</code>. Le noyau Linux
réserve une certaine quantité de mémoire pour la mise en
cache des accès disque. Sous Solaris par contre, il faut disposer
de suffisamment de mémoire RAM pour créer un processus,
et si ce n'est pas le cas, httpd va démarrer avec un
message d'erreur du style "No space left on device" dans
le journal des erreurs, et sera incapable de créer
d'autres processus httpd enfants ; une valeur trop
élevée pour <code>MaxClients</code> constituera alors
réellement un désavantage.
</p>
<h4><a name="selecting-your-mpm" id="selecting-your-mpm">Choisir votre MPM
</a></h4>
<p>La commutation entre threads est plus
aisée pour le système, et ceux-ci consomment moins de
ressources que les processus ; c'est la raison
principale pour laquelle il est recommandé de choisir un
MPM threadé. Et
ceci est encore plus flagrant pour certains systèmes
d'exploitation que pour d'autres. Par exemple, sous
Solaris ou AIX, la manipulation des processus est assez
lourde en termes de ressources système ; l'utilisation
d'un MPM threadé est donc tout à fait indiquée pour ces
systèmes. Sous Linux en revanche, l'implémentation des
threads utilise en fait un processus par thread. Les
processus Linux sont assez légers, mais cela signifie qu'un
MPM threadé présentera ici un gain en performance
moindre que sous d'autres systèmes.
</p>
<p>Dans certaines situations cependant, l'utilisation
d'un MPM threadé peut induire des problèmes de
stabilité. Par exemple, si un processus enfant du MPM
prefork se crashe, au plus une connexion client sera
affectée ; par contre, si un processus enfant threadé se
crashe, ce sont tous les threads de ce processus qui
vont se crasher à leur tour, ce qui signifie que tous
les clients qui étaient servis par ce processus verront
leur connexion interrompue. De plus, certains problèmes
de sécurité des threads ("thread-safety")
peuvent apparaître, particulièrement avec les
bibliothèques tierces. Avec les applications threadées,
les différents threads peuvent avoir accès aux mêmes
variables sans distinction, sans savoir si une variable
n'a pas été modifiée par un autre thread.
</p>
<p>Ce problème a fait l'objet d'un point sensible au
sein de la communauté PHP car Le processeur PHP repose
fortement sur des bibliothèques tierces, et il n'est pas
garanti que la totalité d'entre elles soient
"thread-safe". Bonne nouvelle cependant : si vous
exécutez Apache sous Linux, vous pouvez utiliser PHP
avec le MPM prefork sans craindre une diminution de
performance trop importante par rapport à une option
threadée.
</p>
<h4><a name="spinning-locks" id="spinning-locks">Verrous tournants</a></h4>
<p>Apache httpd maintient un verrou inter-processus du
point de vue de son écoute du réseau. Dans les faits,
cela signifie qu'un seul processus httpd enfant à la
fois peut recevoir une requête. Ainsi, soient les autres
processus en profitent alors pour traiter les requêtes
qu'ils ont déjà reçues, soient ils attendent de pouvoir
à leur tour récupérer le verrou et ainsi écouter le
réseau pour recevoir une nouvelle requête. Ceci peut se
voir comme une porte tournante par laquelle un seul
processus peut passer à la fois. Sur un serveur web
fortement chargé où les requêtes arrivent constamment,
la porte tourne rapidement et les requêtes sont
acceptées à un rythme soutenu. Sur un serveur faiblement
chargé en revanche, le processus qui "détient"
le verrou est suceptible de garder sa porte ouverte un
certain temps durant lequel tous les autres processus
seront inactifs, attendant de pouvoir s'approprier le
verrou. Dans une telle situation, le processus parent
pourra décider d'arrêter quelques processus enfants en
fonction de la valeur de la directive
<code>MaxSpareServers</code>.</p>
<h4><a name="the-thundering-herd" id="the-thundering-herd">L'assaut de la foule
</a></h4>
<p>La fonction de l'"accept mutex" (c'est le nom donné au
verrou inter-processus) consiste à gérer la réception
des requêtes de manière ordonnée. Si ce verrou est
absent, le syndrome de l'"assaut de la foule" peut
apparaître.
</p>
<p>Imaginez une équipe de football américain en attente
devant la ligne de remise en jeu. Si les joueurs se
comportaient comme des processus Apache, ils se
précipiteraient tous à la fois pour récupérer la balle au
signal de la reprise. Un seul d'entre eux y
parviendrait, et tous les autres n'auraient plus qu'à se
regrouper à nouveau sur la ligne jusqu'à la reprise
suivante. Dans cette métaphore, c'est le quaterback qui
va jouer le rôle d'"accept mutex" en donnant la balle
au joueur approprié.
</p>
<p>La transmission d'une telle quantité d'informations
représente naturellement beaucoup de travail et, comme
une personne intelligente, un serveur intelligent
tentera d'éviter cette surcharge dans la mesure du
possible, d'où l'idée de la porte tournante. Dans les
dernières années, de nombreux systèmes d'exploitation,
comme Linux et Solaris, ont développé du code pour
éviter le syndrome de l'"assaut de la foule". Apache
reconnaît ce code, et si vous n'effectuez qu'une seule
écoute du réseau, autrement dit si vous n'utilisez que
le serveur principal ou un seul serveur virtuel, Apache
n'utilisera pas d'"accept mutex" ; par contre, si vous
effectuez plusieurs écoutes du réseau (par exemple si
un serveur virtuel sert les requêtes SSL), Apache
utilisera un "accept mutex" afin d'éviter les conflits
internes.
</p>
<p>Vous pouvez manipuler l'"accept mutex" via la
directive <code>AcceptMutex</code>. Cette dernière
permet en particulier de fermer l'"accept mutex", mais
aussi de sélectionner le mécanisme de verrouillage. Les
mécanismes de verrouillage courants comprennent fcntl,
les sémaphores System V et le verrouillage par threads.
Tous ne sont pas supportés par toutes les plateformes,
et leur disponibilité dépend aussi des options de
compilation. Les différents mécanismes de verrouillage
peuvent avoir des exigences particulières en matière de
ressources système ; il est donc recommandé de les
utiliser avec précautions.
</p>
<p>Il n'existe aucune raison particulière pour
désactiver l'"accept mutex". Apache détermine
automatiquement s'il doit utiliser ou non mutex sur
votre plateforme en fonction du nombre d'écoutes réseau
de votre serveur, comme décrit précédemment.
</p>
<h3><a name="tuning-the-operating-system" id="tuning-the-operating-system">Optimisation du système d'exploitation
</a></h3>
<p>Souvent, les utilisateurs recherchent le paramètre magique qui va
multiplier par quatre les performances de leur système. En
fait, les systèmes de type Unix actuels sont déjà optimisés
à l'origine, et il n'y a plus grand chose à faire pour
améliorer leurs performances. L'administrateur peut
cependant encore effectuer quelques modifications qui
permettront de peaufiner la configuration.
</p>
<h4><a name="ram-and-swap-space" id="ram-and-swap-space">RAM et swap
</a></h4>
<p>Le leitmotiv en matière de mémoire est souvent "plus
on en a, mieux c'est". En effet, comme nous avons dit
plus haut, la mémoire inutilisée peut être
avantageusement utilisée comme cache du système de
fichiers. Plus vous chargez de modules, plus les processus
Apache grossissent, et ceci d'autant plus si vous
utilisez des modules qui génèrent des contenus
dynamiques comme PHP et mod_perl. Un gros fichier de
configuration - avec de nombreux serveurs virtuels - a
aussi tendance à augmenter l'empreinte mémoire des
processus. Une quantité de mémoire importante vous
permettra d'exécuter Apache avec plus de processus
enfants, et donc de traiter d'avantage de requêtes
simultanément.
</p>
<p>Même si les différentes plateformes traitent leur
mémoire virtuelle de différentes manières, il est
déconseillé de configurer un espace disque de swap
inférieur à la mémoire RAM. En effet, le système de mémoire
virtuelle a été conçu de manière à prendre le relai
lorsque la mémoire RAM fait défaut, et lorsque l'espace
disque, et donc l'espace de swap vient à manquer, votre
serveur risque de s'arrêter. Vous devrez alors
redémarrer physiquement votre serveur, et votre
hébergeur pourra vous facturer le service.
</p>
<p>Evidemment, ce genre problème survient au moment le
plus défavorable : lorsque le monde vient découvrir votre
site web et se présente avec insistance à votre porte.
Si votre espace de swap est suffisant, même si la
machine sera de plus en plus surchargée et deviendra
très très lente car le système devra swapper les pages
entre la mémoire et le disque, lorsque la charge diminuera à
nouveau, le système reviendra dans son mode de
fonctionnement normal. Rappelez-vous que vous disposez
de la directive <code>MaxClients</code> pour garder le contrôle.
</p>
<p>La plupart des systèmes de type Unix utilisent des
partitions dédiées au swap. Au démarrage du système,
celui-ci enregistre toutes les partitions de swap du ou
des disques en fonction du type de la partition ou du
contenu du fichier <code>/etc/fstab</code> et les
active de manière automatique. Lorsque vous ajoutez un
disque, ou lorsque vous installez le système
d'exploitation, assurez-vous d'allouer suffisamment
d'espace de swap afin de rester en adéquation avec une
éventuelle augmentation de la mémoire RAM. La
réallocation d'espace disque sur un système en
production est en effet pénible et fastidieuse.
</p>
<p>Prévoyez un espace de swap de deux fois la taille de
votre mémoire RAM, et même jusqu'à quatre fois lorsque
les surcharges peuvent s'avérer fréquentes. Assurez-vous
de réajuster ces valeurs lorsque vous augmentez la
quantité de mémoire RAM de votre système. En secours,
vous pouvez aussi utilisez un fichier comme espace de
swap. Pour ce faire, vous trouverez les instructions
dans les pages de manuel de <code>mkswap</code> et
<code>swapon</code>, ou dans celles des programmes de
<code>swap</code>.
</p>
<h4><a name="ulimit-files-and-processes" id="ulimit-files-and-processes">ulimit: fichiers et processus
</a></h4>
<p>Supposons que vous disposiez d'une machine possédant
une énorme quantité de mémoire RAM et un processeur aux
performances astronomiques ; vous pourrez alors exécuter
des centaines de processus Apache selon vos besoins,
mais tout en restant en deçà des limites imposées par le
noyau de votre système.
</p>
<p>Considérez maintenant une situation où plusieurs
centaines de serveurs web sont en cours d'exécution ; si
certains d'entre eux doivent à leur tour lancer des
processus CGI, le nombre maximum de processus autorisé
par le noyau sera vite atteint.
</p>
<p>Dans ce cas, vous pouvez modifier cette limite avec
la commande :
</p>
<div class="example"><p><code>
ulimit [-H|-S] -u [nouvelle valeur]
</code></p></div>
<p>Cette modification doit être effectuée avant le
démarrage du serveur, car la nouvelle valeur ne sera
prise en compte que dans le shell courant et pour les
programmes lancés depuis ce dernier. Dans les derniers
noyaux Linux, la valeur par défaut a été fixée à 2048.
Sous FreeBSD, ce nombre semble être limité à la valeur
inhabituelle de 513. Dans le shell par défaut de ce
système, <code>csh</code>, la commande équivalente est
<code>limit</code> et possède une syntaxe analogue à
celle de la commande de style Bourne <code>ulimit</code> :
</p>
<div class="example"><p><code>
limit [-h] maxproc [newvalue]
</code></p></div>
<p>En outre, le noyau peut limiter le nombre de fichiers
ouverts par processus. Ce n'est généralement pas un
problème pour les serveurs dont les processus sont lancés
à l'avance, et où chacun de ceux-ci ne traite qu'une
requête à la fois. Les processus des serveurs threadés,
quant à eux, traitent plusieurs requêtes simultanément,
et sont d'avantage susceptibles de dépasser la limite du
nombre de descripteurs de fichiers. Vous pouvez alors
augmenter cette valeur limite du nombre de fichiers
ouverts avec la commande :
</p>
<div class="example"><p><code>ulimit -n [newvalue]
</code></p></div>
<p>Là encore, cette modification doit être effectuée
avant le démarrage du serveur Apache.
</p>
<h4><a name="setting-user-limits-on-system-startup" id="setting-user-limits-on-system-startup">Définition des limites en fonction de l'utilisateur ou du
groupe au démarrage du système
</a></h4>
<p>Sous Linux, vous pouvez définir les paramètres de
ulimit au démarrage en éditant le fichier
<code>/etc/security/limits.conf</code>. Ce fichier vous
permet de définir des limites "soft" et "hard"
en fonction de l'utilisateur ou du groupe ;
vous y trouverez aussi des commentaires explicatifs des
différentes options. Pour que ce fichier soit pris en
compte, le fichier <code>/etc/pam.d/login</code> doit
contenir la ligne :
</p>
<div class="example"><p><code>session required /lib/security/pam_limits.so
</code></p></div>
<p>Chaque item peut posséder une valeur "soft" et
"hard" : la première est la valeur
par défaut, et la seconde la valeur maximale de cet
item.
</p>
<p>Dans le fichier <code>/etc/login.conf</code> de
FreeBSD, ces valeurs peuvent être limitées ou étendues à
tout le système de manière analogue au fichier
<code>limits.conf</code>. Les limites "soft" sont
spécifiées via le paramètre <code>-cur</code>, et les
limites "hard" via le paramètre <code>-max</code>.
</p>
<p>Solaris possède un mécanisme similaire pour manipuler
les valeurs limites au démarrage du système : dans le
fichier <code>/etc/system</code>, vous pouvez définir au
démarrage des paramètres du noyau valables pour
l'ensemble du système. Ce sont les mêmes paramètres que
ceux définis à l'exécution par le débogueur de noyau
<code>mdb</code>. Les commandes équivalentes à ulimit -u
pour définir les limites hard et soft seront du style :
</p>
<div class="example"><p><code>
set rlim_fd_max=65536<br />
set rlim_fd_cur=2048
</code></p></div>
<p>Solaris calcule le nombre maximal de processus
autorisé par utilisateur (<code>maxuprc</code>) en
fonction de la mémoire système disponible
(<code>maxusers</code>). Vous pouvez obtenir ces valeurs
avec la commande :
</p>
<div class="example"><p><code>sysdef -i | grep maximum
</code></p></div>
<p>Il est cependant déconseillé de les modifier.
</p>
<h4><a name="turn-off-unused-services-and-modules" id="turn-off-unused-services-and-modules">Désactiver les services et modules non utilisés
</a></h4>
<p>Dans la plupart des distributions Unix et Linux, de
nombreux services sont activés par défaut, et vous n'
avez probablement besoin que d'une minorité d'entre eux.
Par exemple, votre serveur web n'a pas besoin de
sendmail, de fournir le service NFS, etc... Désactivez
les tout simplement.
</p>
<p>Pour ce faire, sous RedHat Linux, vous
disposez de l'utilitaire chkconfig en ligne de commande.
Sous Solaris, les commandes <code>svcs</code> et
<code>svcadm</code> vous permettent respectivement
de lister les services activés et de désactiver ceux
dont vous n'avez pas besoin.
</p>
<p>Vous devez aussi prêter attention aux modules Apache
chargés par défaut. La plupart des distributions binaires
d'Apache httpd et des versions préinstallées fournies
avec les distributions de Linux chargent les modules
Apache via la directive
<code class="directive">LoadModule</code>.
</p>
<p>Les modules inutilisés peuvent être désactivés : si
vous n'avez pas besoin de leurs fonctionnalités et des
directives de configuration qu'ils implémentent,
désactivez-les en commentant les lignes
<code class="directive">LoadModule</code> correspondantes. Vous
devez cependant lire la documentation relative à ces
modules avant de les désactiver, et garder à l'esprit que
la désactivation d'un module très peu gourmand en
ressources n'est pas absolument nécessaire.
</p>
</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="caching-content" id="caching-content">Mise en cache des contenus
</a> <a title="Lien permanent" href="#caching-content" class="permalink">&para;</a></h2>
<p>Les requêtes impliquant des contenus dynamiques nécessitent
en général d'avantage de ressources que les
requêtes pour des contenus statiques. Les contenus statiques
consistent en simples pages issues de documents ou images
sur disque, et sont servis très rapidement. En outre, de
nombreux systèmes d'exploitation mettent automatiquement en
cache en mémoire les contenus des fichiers fréquemment accédés.
</p>
<p>Comme indiqué précédemment, le traitement des requêtes dynamiques peut
nécessiter beaucoup plus de ressources. L'exécution de scripts
CGI, le transfert de requêtes à un serveur d'applications
externe, ou les accès à une base de données peuvent impliquer
des temps d'attente et charges de travail significatifs pour un
serveur web fortement sollicité. Dans de nombreuses
circonstances, vous pourrez alors améliorer les performances en
transformant les requêtes dynamiques courantes en requêtes
statiques. Pour ce faire, deux approches seront discutées dans
la suite de cette section.
</p>
<h3><a name="making-popular-pages-static" id="making-popular-pages-static">Transformation des pages courantes en contenus
statiques
</a></h3>
<p>En générant à l'avance les réponses pour les requêtes les
plus courantes de votre application, vous pouvez améliorer
de manière significative les performances de votre serveur
sans abandonner la flexibilité des contenus générés
dynamiquement. Par exemple, si votre application est un
service de livraison de fleurs, vous aurez tout intérêt à
générer à l'avance les pages de votre catalogue concernant
les roses rouges dans les semaines précédant le jour de la
Saint Valentin. Lorsqu'un utilisateur cherchera des roses
rouges, il téléchargera alors les pages générées à
l'avance. Par contre, les recherches de roses jaunes seront
quant à elles traitées directement via une requête vers la
base de données. Pour effectuer ces aiguillages de requêtes,
vous disposez d'un outil particulièrement approprié fourni
avec Apache : le module mod_rewrite.
</p>
<h4><a name="example-a-statically-rendered-blog" id="example-a-statically-rendered-blog">Exemple : un blog servi statiquement
</a></h4>
<p>Blosxom est un programme CGI de journalisation web
léger. Il est écrit en Perl et utilise des fichiers
texte pour ses entrées. Outre sa qualité de programme
CGI, Blosxom peut être exécuté en ligne de commande pour
générer à l'avance des pages de blog. Lorsque votre blog
commence à être lu par un grand nombre de personnes, la
génération à l'avance de pages en HTML satique peut
améliorer de manière significative les performances de
votre serveur.
</p>
<p>Pour générer des pages statiques avec blosxom, éditez
le script CGI selon la documentation. Définissez la
variable $static dir à la valeur de
<code class="directive">DocumentRoot</code> de votre serveur
web, et exécutez le script en ligne de commande comme
suit :
</p>
<div class="example"><p><code>$ perl blosxom.cgi -password='whateveryourpassword'
</code></p></div>
<p>Vous pouvez exécuter ce script périodiquement via
cron, à chaque fois que vous ajoutez un nouveau contenu. Pour
faire en sorte qu'Apache substitue les pages
statiques au contenu dynamique, nous
utiliserons mod_rewrite. Ce module est fourni avec le
code source d'Apache, mais n'est pas compilé par défaut.
Pour le compiler avec la distribution d'Apache, vous
pouvez utiliser l'option de la commande configure
<code>--enable-rewrite[=shared]</code>. De nombreuses
distributions binaires d'Apache sont fournies avec
<code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> inclus. Dans l'exemple
suivant, un serveur virtuel Apache utilise les pages de
blog générées à l'avance :
</p>
<pre class="prettyprint lang-config">Listen *:8001
&lt;VirtualHost *:8001&gt;
ServerName blog.sandla.org:8001
ServerAdmin sander@temme.net
DocumentRoot "/home/sctemme/inst/blog/httpd/htdocs"
&lt;Directory "/home/sctemme/inst/blog/httpd/htdocs"&gt;
Options +Indexes
Require all granted
RewriteEngine on
RewriteCond "%{REQUEST_FILENAME}" "!-f"
RewriteCond "%{REQUEST_FILENAME}" "!-d"
RewriteRule "^(.*)$" "/cgi-bin/blosxom.cgi/$1" [L,QSA]
&lt;/Directory&gt;
RewriteLog "/home/sctemme/inst/blog/httpd/logs/rewrite_log"
RewriteLogLevel 9
ErrorLog "/home/sctemme/inst/blog/httpd/logs/error_log"
LogLevel debug
CustomLog "/home/sctemme/inst/blog/httpd/logs/access_log common"
ScriptAlias "/cgi-bin/" "/home/sctemme/inst/blog/bin/"
&lt;Directory "/home/sctemme/inst/blog/bin"&gt;
Options +ExecCGI
Require all granted
&lt;/Directory&gt;
&lt;/VirtualHost&gt;</pre>
<p>
Si les directives <code class="directive">RewriteCond</code>
indiquent que la ressource demandée n'existe ni en tant que
fichier, ni en tant que répertoire, son
chemin sera redirigé par la directive
<code class="directive">RewriteRule</code> vers le programme
CGI Blosxom qui va générer la réponse. Blosxom
utilise Path Info pour spécifier les entrées de blog
en tant que pages d'index, et si un chemin dans
Blosxom existe en tant que fichier statique dans le système de
fichiers, c'est ce dernier qui sera par conséquent privilégié.
Toute requête dont la réponse n'a pas été générée à
l'avance sera traitée par le programme CGI. Cela
signifie que les entrées individuelles comme les
commentaires seront toujours servies par le
programme CGI, et seront donc toujours visibles.
Cette configuration permet aussi de ne pas faire
apparaître le programme CGI Blosxom dans l'URL de la barre
d'adresse. Enfin, mod_rewrite est un module extrêmement
souple et puissant ; prenez le temps de bien
l'étudier afin de parvenir à la configuration qui
correspondra le mieux à votre situation.
</p>
<h3><a name="caching-content-with-mod_cache" id="caching-content-with-mod_cache">Mise en cache du contenu avec mod_cache
</a></h3>
<p>Le module mod_cache implémente une mise en cache
intelligente des réponses HTTP : il tient compte des délais
de péremption et des contraintes en matière de contenu
inhérentes à la spécification HTTP. Le module mod_cache met
en cache les URL des contenus des réponses. Si un contenu envoyé au
client peut être mis en cache, il est sauvegardé sur disque.
Les requêtes ultérieures pour cette URL seront alors servies
directement depuis le cache. Le module fournisseur pour
mod_cache, mod_disk_cache, détermine la manière dont les
contenus sont stockés sur disque. La plupart des systèmes de
serveur possèdent plus d'espace disque que de mémoire, et il
est bon de garder à l'esprit que certains noyaux système mettent en
cache de manière transparente en mémoire les contenus sur
disque fréquemment accédés ; il n'est donc pas très utile de
répéter cette opération au niveau du serveur.
</p>
<p>Pour mettre en oeuvre une mise en cache de contenu
efficace et éviter de présenter à l'utilisateur un contenu
invalide ou périmé, l'application qui génère le contenu à
jour doit envoyer les en-têtes de réponse corrects. En
effet, en l'absence d'en-têtes comme <code>Etag:</code>,
<code>Last-Modified:</code> ou <code>Expires:</code>,
<code class="module"><a href="../mod/mod_cache.html">mod_cache</a></code> ne sera pas en mesure de décider
de manière appropriée
s'il doit mettre le contenu en cache, s'il doit le servir
directement depuis ce dernier, ou s'il doit tout simplement
ne rien faire. Lorsque vous testerez la mise en cache, vous
devrez peut-être modifier votre application ou, en cas
d'impossibilité, désactiver de manière sélective la mise en
cache des URLs qui posent problème. Les modules mod_cache ne
sont pas compilés par défaut ; pour ce faire, vous devez
utiliser l'option <code>--enable-cache[=shared]</code> du
script configure. Si vous utilisez une distribution binaire
d'Apache httpd, ou si elle fait partie de votre portage ou
de votre sélection de paquets, <code class="module"><a href="../mod/mod_cache.html">mod_cache</a></code>
sera probablement déjà inclus.
</p>
<h4><a name="example-wiki" id="example-wiki">Exemple : wiki.apache.org
</a></h4>
<p>
Le Wiki de l'Apache Software Foundation est servi
par MoinMoin. MoinMoin est écrit en Python et
s'exécute en tant que programme CGI. A l'heure
actuelle, toute tentative pour l'exécuter via
mod_python s'est soldée par un échec. Le programme
CGI induit une charge inacceptable sur le serveur,
particulièrement lorsque le Wiki est indexé par des
moteurs de recherche comme Google. Pour alléger la
charge de la machine, l'équipe d'infrastructure
d'Apache s'est tournée vers mod_cache. Il s'est
avéré que <a href="/httpd/MoinMoin">MoinMoin</a>
nécessitait un petit patch pour adopter un
comportement approprié en aval du serveur de mise
en cache : certaines requêtes ne pouvaient jamais
être mises en cache, et les modules Python
concernés ont été mis à jour pour pouvoir envoyer
les en-têtes de réponse HTTP corrects. Après cette
modification, la mise en cache en amont du Wiki a
été activée via l'insertion des lignes suivantes
dans le fichier de configuration
<code>httpd.conf</code> :
</p>
<pre class="prettyprint lang-config">CacheRoot /raid1/cacheroot
CacheEnable disk /
# Une page modifiée il y a 100 minutes expirera dans 10 minutes
CacheLastModifiedFactor .1
# Dans tous les cas, vérifier la validité des pages après 6 heures
CacheMaxExpire 21600</pre>
<p>Cette configuration essaie de mettre en cache tout
contenu de son serveur virtuel. Elle ne mettra jamais en
cache un contenu plus vieux que 6 heures (voir la
directive <code class="directive"><a href="../mod/mod_cache.html#cachemaxexpire">CacheMaxExpire</a></code>). Si
l'en-tête <code>Expires:</code> est absent de la
réponse, <code class="module"><a href="../mod/mod_cache.html">mod_cache</a></code> va calculer une date
d'expiration en fonction du contenu de l'en-tête
<code>Last-Modified:</code>. Le principe de ce calcul
qui utilise la directive <code class="directive"><a href="../mod/mod_cache.html#cachelastmodifiedfactor">CacheLastModifiedFactor</a></code>
se base sur l'hypothèse que si une page a été modifiée
récemment, il y a de fortes chances pour qu'elle le soit
à nouveau dans un futur proche et devra donc être remise
en cache.
</p>
<p>
Notez qu'il peut s'avérer payant de
<em>désactiver</em> l'en-tête <code>ETag:</code> :
pour les fichiers inférieurs à 1 ko, le serveur
doit calculer la somme de vérification checksum (en
général MD5) et envoyer une réponse <code>304 Not
Modified</code>, ce qui utilise des ressources CPU
et réseau pour le transfert (1 paquet TCP). Pour les
ressources supérieures à 1 ko, les ressources CPU
consommées peuvent devenir importantes car l'en-tête
est calculé à chaque requête. Malheureusement, il
n'existe actuellement aucun moyen pour mettre en
cache ces en-têtes.
</p>
<pre class="prettyprint lang-config">&lt;FilesMatch "\.(jpe?g|png|gif|js|css|x?html|xml)"&gt;
FileETag None
&lt;/FilesMatch&gt;</pre>
<p>
Dans l'exemple précédent: la génération d'un en-tête
<code>ETag:</code> sera désactivée pour la plupart
des ressources statiques. Le serveur ne génère pas
ces en-têtes pour les ressources dynamiques.
</p>
</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="further-considerations" id="further-considerations">Pour aller plus loin
</a> <a title="Lien permanent" href="#further-considerations" class="permalink">&para;</a></h2>
<p>Armés du savoir-faire pour personnaliser un système afin
qu'il affiche les performances désirées, nous découvrirons vite
qu'<em>1</em> sytème à lui seul peut constituer un goulot
d'étranglement. A ce sujet, la page du Wiki <a href="http://wiki.apache.org/httpd/PerformanceScalingOut">PerformanceScalingOut</a>
décrit comment adapter un système à mesure qu'il prend de
l'ampleur, ou comment personnaliser plusieurs systèmes dans leur
ensemble.
</p>
</div></div>
<div class="bottomlang">
<p><span>Langues Disponibles: </span><a href="../en/misc/perf-scaling.html" hreflang="en" rel="alternate" title="English">&nbsp;en&nbsp;</a> |
<a href="../es/misc/perf-scaling.html" hreflang="es" rel="alternate" title="Español">&nbsp;es&nbsp;</a> |
<a href="../fr/misc/perf-scaling.html" title="Français">&nbsp;fr&nbsp;</a></p>
</div><div class="top"><a href="#page-header"><img src="../images/up.gif" alt="top" /></a></div><div class="section"><h2><a id="comments_section" name="comments_section">Commentaires</a></h2><div class="warning"><strong>Notice:</strong><br />This is not a Q&amp;A section. Comments placed here should be pointed towards suggestions on improving the documentation or server, and may be removed by our moderators if they are either implemented or considered invalid/off-topic. Questions on how to manage the Apache HTTP Server should be directed at either our IRC channel, #httpd, on Libera.chat, or sent to our <a href="https://httpd.apache.org/lists.html">mailing lists</a>.</div>
<script type="text/javascript"><!--//--><![CDATA[//><!--
var comments_shortname = 'httpd';
var comments_identifier = 'http://httpd.apache.org/docs/trunk/misc/perf-scaling.html';
(function(w, d) {
if (w.location.hostname.toLowerCase() == "httpd.apache.org") {
d.write('<div id="comments_thread"><\/div>');
var s = d.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = 'https://comments.apache.org/show_comments.lua?site=' + comments_shortname + '&page=' + comments_identifier;
(d.getElementsByTagName('head')[0] || d.getElementsByTagName('body')[0]).appendChild(s);
}
else {
d.write('<div id="comments_thread">Comments are disabled for this page at the moment.<\/div>');
}
})(window, document);
//--><!]]></script></div><div id="footer">
<p class="apache">Copyright 2023 The Apache Software Foundation.<br />Autorisé sous <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
<p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/quickreference.html">Directives</a> | <a href="http://wiki.apache.org/httpd/FAQ">FAQ</a> | <a href="../glossary.html">Glossaire</a> | <a href="../sitemap.html">Plan du site</a></p></div><script type="text/javascript"><!--//--><![CDATA[//><!--
if (typeof(prettyPrint) !== 'undefined') {
prettyPrint();
}
//--><!]]></script>
</body></html>