Note concernant les distributions, la configuration Apache de Debian est relativement bien faite, par contre sur CentOS, c'est une catastrophe. Cette page parlera surtout donc de CentOS. Notez que les processus et commandes différents d'une Debian à CentOS. Sur Debian, le nom utilisé est apache2 (conf : /etc/apache2/apache2.conf) alors que sur CentOS le nom utilisé est httpd (conf : /etc/httpd/conf/httpd.conf) Dans les scripts donnés sur cette page, veuillez à remplacer httpd/apache2 selon votre distribution.
Utilisation Mémoire Apache
Apache fonctionne de manière modulaire. Apache va charger un certains nombre de processus selon la charge serveur et la configuration pré-établie. Vous serez donc limiter par les ressources hardwares de votre serveur et ne pourrez charger qu'un certains nombre de processus notamment la mémoire disponible. Une bonne configuraton peux permettre de répondre à des charges ponctuelles ou mettre à mal le serveur (si Apache s'amuse par exemple à charger et décharger des processus enfants).
Dans un premier temps, ce qu'il faut faire c'est de répondre la taille en mémoire d'Apache afin de pouvoir charger un maximum de processus Apache selon les ressources disponibles. Il ne faut pas que le serveur se mette à swapper, sinon les performances seront dégradées (Accès disques etc).
Pour visualiser l'utilisation mémoire Apache, vous pouvez utiliser la commande top.

Rapidement pour donner les grandes lignes :
- RES : Taille mémoire résidente, c'est la taille mémoire consommé par le processus sans le SWAP.
- SHR : Taille mémoire partagée : c'est la portion de mémoire VIRT partagée par le processus avec d'autres processus.
- VIRT : Taille mémoire virtuelle d'un processus : c'est la mémoire qui comprend en plus les bibliothèques chargées par le processus.
Optimisation Apache/PHP
Dans un premier temps, nous allons limiter l'utilisation mémoire des processus Apache.
Pour cela, on va décharger les modules inutiles (qui change selon le serveur).
Listons les modules chargés avec la commande httpd -M (sous Debian : apachectl -M).
On constate notamment des modules par forcément nécessaires et surtout python et perl qui ne sont pas utiles dans mon cas. Vous trouverez une liste des modules à la page suivante : http://httpd.apache.org/docs/2.0/mod/

Editons /etc/httpd/conf/httpd.conf pour commenter quelques modules :
Code : Tout sélectionner
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule auth_digest_module modules/mod_auth_digest.so
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_alias_module modules/mod_authn_alias.so
LoadModule authn_anon_module modules/mod_authn_anon.so
#LoadModule authn_dbm_module modules/mod_authn_dbm.so
#LoadModule authn_default_module modules/mod_authn_default.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_owner_module modules/mod_authz_owner.so
#LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
#LoadModule authz_dbm_module modules/mod_authz_dbm.so
LoadModule authz_default_module modules/mod_authz_default.so
#LoadModule ldap_module modules/mod_ldap.so
#LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
LoadModule include_module modules/mod_include.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule logio_module modules/mod_logio.so
LoadModule env_module modules/mod_env.so
LoadModule ext_filter_module modules/mod_ext_filter.so
LoadModule mime_magic_module modules/mod_mime_magic.so
LoadModule expires_module modules/mod_expires.so
LoadModule deflate_module modules/mod_deflate.so
LoadModule headers_module modules/mod_headers.so
LoadModule usertrack_module modules/mod_usertrack.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule mime_module modules/mod_mime.so
LoadModule dav_module modules/mod_dav.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule info_module modules/mod_info.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule vhost_alias_module modules/mod_vhost_alias.so
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule dir_module modules/mod_dir.so
LoadModule actions_module modules/mod_actions.so
#LoadModule speling_module modules/mod_speling.so
#LoadModule userdir_module modules/mod_userdir.so
LoadModule alias_module modules/mod_alias.so
LoadModule rewrite_module modules/mod_rewrite.so
#LoadModule proxy_module modules/mod_proxy.so
#LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
#LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
#LoadModule proxy_http_module modules/mod_proxy_http.so
#LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule cache_module modules/mod_cache.so
#LoadModule suexec_module modules/mod_suexec.so
LoadModule disk_cache_module modules/mod_disk_cache.so
LoadModule file_cache_module modules/mod_file_cache.so
LoadModule mem_cache_module modules/mod_mem_cache.so
#LoadModule cgi_module modules/mod_cgi.so
LoadModule version_module modules/mod_version.so

Sur CentOs pour décharger Python, Perl et compagnie :
mv /etc/httpd/conf.d/python.{conf,old}
mv /etc/httpd/conf.d/python.{conf,old}
mv /etc/httpd/conf.d/perl.{conf,old}
mv /etc/httpd/conf.d/rpaf.{conf,old}
mv /etc/httpd/conf.d/proxy_ajp.{conf,old}
mv /etc/httpd/conf.d/aclr.{conf,old}
mv /etc/httpd/conf.d/webalizer.{conf,old}
De même au niveau des modules PHP, vous pouvez en désactiver afin de réduire l'utilisation mémoire (Debian : /etc/php5/mods-available/ ).
Sur la machine CentOs :
Vous pouvez aussi charger une page contenant phpinfo(); pour avoir la liste des modules.[root@nsxxxx-xxx ~]# ls -lh /etc/php.d/
total 88K
-rw-r--r-- 1 root root 129 mars 21 19:25 00-ioncube-loader.ini
-rw-r--r-- 1 root root 81 mars 31 2013 apc.ini
-rw-r--r-- 1 root root 49 déc. 11 2013 curl.ini
-rw-r--r-- 1 root root 47 déc. 11 2013 dom.ini
-rw-r--r-- 1 root root 57 déc. 11 2013 fileinfo.ini
-rw-r--r-- 1 root root 45 déc. 11 2013 gd.ini
-rw-r--r-- 1 root root 49 déc. 11 2013 imap.ini
-rw-r--r-- 1 root root 49 déc. 11 2013 json.ini
-rw-r--r-- 1 root root 57 déc. 11 2013 mbstring.ini
-rw-r--r-- 1 root root 53 déc. 11 2013 mysqli.ini
-rw-r--r-- 1 root root 51 déc. 11 2013 mysql.ini
-rw-r--r-- 1 root root 47 déc. 11 2013 pdo.ini
-rw-r--r-- 1 root root 59 déc. 11 2013 pdo_mysql.ini
-rw-r--r-- 1 root root 61 déc. 11 2013 pdo_sqlite.ini
-rw-r--r-- 1 root root 49 déc. 11 2013 phar.ini
-rw-r--r-- 1 root root 79 avril 27 2012 sqlite.ini
-rw-r--r-- 1 root root 49 déc. 11 2013 wddx.ini
-rw-r--r-- 1 root root 59 déc. 11 2013 xmlreader.ini
-rw-r--r-- 1 root root 59 déc. 11 2013 xmlwriter.ini
-rw-r--r-- 1 root root 47 déc. 11 2013 xsl.ini
-rw-r--r-- 1 root root 214 août 15 2013 zend_extensions_psa.ini
-rw-r--r-- 1 root root 47 déc. 11 2013 zip.ini
Ou encore en ligne de commande avec la commande php -m
Particularité de Debian qui embarque beaucoup de modules par défaut, d'ailleurs dans les informations du package :
Il est impossible de décharger les modules, il faut compiler sa propre version de PHP.Les extensions suivantes sont incorporées : bcmath, bz2, calendar, Core, ctype, date, dba, dom, ereg, exif, fileinfo, filter, ftp, gettext, hash, iconv, json, libxml, mbstring, mhash,
openssl, pcre, Phar, posix, Reflection, session, shmop, SimpleXML, soap, sockets, SPL, standard, sysvmsg, sysvsem, sysvshm, tokenizer, wddx, xml, xmlreader, xmlwriter, zip, zlib.
Une fois le ménage fait :
Testons la configuration :
(Debian : service apache2 configtest)service httpd configtest
relançons Apache :
(Debian : service apache2 graceful)service httpd graceful
Le RES tombe à environ 14/15Mo et le VIRT à ~325Mo

Comme expliqué dans l'introduction, Apache s'adapte au traffic et charge du serveur en chargeant et déchargeant des processus. La configuration est définie par les éléments suivants :
Pour comprendre :<IfModule prefork.c>
StartServers xxxx
ServerLimit xxxx
MinSpareServers xxxx
MaxSpareServers xxxx
MaxRequestsPerChild 0
MaxClients xxxx
</IfModule>
- StartServers : StartServers définit le nombre de processus créés au démarrage. Cela ne sert à rien de configurer cette valeur trop haute, si le traffic est trop bas, Apache devra tuer les processus en trop.
- ServerLimit :
- MinSpareServers et MaxSpareServers : Ces valeurs définissent le nombre de processus en minimal et maxiaml en attente de requêtes (dormants). MinSpareServers est le nombre de processus minimal créés par le serveur et MaxSpareServers est le nombre de processus maximal. Apache va adapter le nombre de processus créés entre ces deux valeurs selon l'activité du/des site(s).
- MaxClients : C'est le nombre de processus total au maximum créés. Si la valeur est trop basse et l'activité serveur trop importante, Apache ne pourra plus délivrer les pages. Cette limite permet de protéger le serveur contre une surcharge mémoire Apache.
- MaxRequestsPerChild : MaxRequestsPerChild définit le nombre total de demandes que chaque processus serveurs fils sert avant de disparaître.
La valeur MinSpareServers par défaut de votre serveur est 5 ; la valeur MaxSpareServers par défaut de votre serveur est 20. Ces paramètres par défaut devraient être appropriés dans presque toutes les situations. Ne définissez pas une valeur très élevée pour MinSpareServers car cela créera une charge de traitement importante sur le serveur, même si le trafic est faible.
En résumé : MinSpareServers, MaxSpareServers et StartServers sont seulement importants pour déterminer les temps de réponses vis-à-vis des clients.
Car la création de processus prend du temps, si les valeurs ne sont pas bonnes, les temps de réponse s'en feront ressentir.
Une mauvaise configuration peux, pour un même traffic, mettre le serveur à genoux comme il peux se porter très bien.
MaxClient lui permet de déterminer la charge total du serveur, d'où le fait qu'un processus Apache doit prendre le minimum de ressources mémoires, ainsi on peux augmenter la valeur de MaxClient.
Ces valeurs diffèrent selon le traffic du serveur.
Lorsque le MaxClient atteint ses limites, on obtient cette erreur dans le fichier error.log
La valeur MaxClient se calcule de la manière suivante :[Fri Aug 04 02:30:02 2006] [error] server reached MaxClients setting, consider raising the MaxClients setting
((MemoireTotale)(1024)(MB) - Mémoire utilisé par le système) / Memoire RSS/RES
Le script perl suivant permet de calculer les valeurs : http://code.google.com/p/check-httpd-li ... umentation
Le script bash suivant aussi :- HttpdRealAvg : 8.50 MB [excludes shared]
- HttpdSharedAvg : 7.46 MB
- HttpdRealTot : 6347.02 MB [excludes shared]
- HttpdRunning : 733
Httpd Config
- StartServers : 150
- ServerLimit : 2048
- MinSpareServers : 50
- MaxSpareServers : 200
- MaxRequestsPerChild : 0
- MaxClients : 2048
Server Memory
- Cached : 3727.64 MB
- MemFree : 16236.79 MB
- MemTotal : 24165.43 MB
- SwapFree : 1021.27 MB
- SwapTotal : 1021.99 MB
Calculations Summary
- OtherProcsMem : -2153.48 MB (MemTotal - Cached - MemFree - HttpdRealTot - HttpdSharedAvg)
- FreeMemNoHttpd : 26318.91 MB (MemFree + Cached + HttpdRealTot + HttpdSharedAvg)
- MaxLimitHttpdMem : 17415.46 MB (HttpdRealAvg * MaxClients + HttpdSharedAvg)
- AllProcsTotalMem : 15261.98 MB (OtherProcsMem + MaxLimitHttpdMem)
Maximum Values for MemTotal (24165.43 MB)
<IfModule prefork.c>
StartServers 150 # (no change) Default is 5
ServerLimit 3096 # (2048 -> 3096) MaxClients
MinSpareServers 50 # (no change) Default is 5
MaxSpareServers 200 # (no change) Default is 10
MaxRequestsPerChild 0 # (no change) Default is 10000
MaxClients 3096 # (2048 -> 3096) (MemFree + Cached + HttpdRealTot + HttpdSharedAvg) / HttpdRealAvg
</IfModule>
Result
OK: AllProcsTotalMem (15261.98 MB) fits within MemTotal (24165.43 MB).
Code : Tout sélectionner
#!/bin/bash
tome=$(free -m | grep -i mem | awk '{print $2}')
htps=$(ps -aylC httpd |grep "httpd" |awk '{print $8'} |sort -n |tail -n 1)
mysme=$(ps aux | grep 'mysql' | awk '{print $6}' |sort -n |tail -n 1)
rafa=1024
nmysme=$(expr $mysme / $rafa)
nhtps=$(expr $htps / $rafa)
echo -e "\nTotal Memory = $tome"
echo -e "Largest httpd Process = $nhtps"
echo -e "Mysql Memory = $nmysme"
maxc=`expr $tome - $nmysme`
maxcl=`expr $maxc / $nhtps`
echo -e "\nSo, The MaxClients = $maxcl"
echo -e "(we can use nearest round of value from $maxcl)"
Mais la valeur est trop basse en cas de surcharge.Total Memory = 24165
Largest httpd Process = 17
Mysql Memory = 152
So, The MaxClients = 1412
(we can use nearest round of value from 1412)
Voici la configuration pour le serveur donné plus haut (24Go) - encore une fois, c'est à titre d'exemple.
Tout dépend de la configuration Apache et des besoins du serveur.
La commande watch peux vous aider à déterminer si les valeurs mises sont bonnes.<IfModule prefork.c>
StartServers 150
MinSpareServers 50
MaxSpareServers 200
ServerLimit 2048
MaxClients 2048
MaxRequestsPerChild 0
</IfModule>
Si le nombre de processus Apache se rapproche du MaxClients et que vous avez encore de la RAM disponible, alors vous pouvez augmenter sa valeur.watch -n 1 "echo -n 'Apache Processes: ' && ps -C httpd --no-headers | wc -l && free -m"

Autre élément à tester KeepAlive, ceci permet d'activer la persistence des connexions. Plusieurs requêtes HTTP pourront être envoyées sur une même connexion, si la valeur est à Off, une reconnexion TCP doit être effectué ce qui peux augmenter le délai de délivrance des pages. Cela peux être interressant par exemple si vous avez des pages avec beaucoup d'images.
Exemple de valeurs :
KeepAliveTimeout est la durée d'attente de la prochaine requête HTTP sur la même connexion, si vous définissez une valeur trop elevé, les processus enfants (MxxSpareServers) seront trop mobilités et vous pouvez avoir une baisse des performances. MaxKeepAliveRequests est le nombre de requête maximum autorisé pour une même connexion TCP.KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 3
En général, les valeurs ci-dessous sont suffisantes. Pour les serveurs WEB avec un gros traffic, il peut-être recommandé de limiter les logs voir de les désactiver. Ceci limitera les accès disques. Vous pouvez passer le warn en error pour ne logguer que les erreurs :
Attention aussi au paramètre log_errors dans php.ini qui peux forcer le log.LogLevel warn => LogLevel error
Optimiser PHP
Vous pouvez adjoindre des cache et autres optimiser tel que :
- APC : http://pecl.php.net/package/APC
- eAccelerator : http://bin63.com/how-to-install-eaccele ... on-freebsd
- Zend Optimiser : http://www.ntchosting.com/php/zend-opti ... sting.html
Vous pouvez aussi forcer et gérer la compression.
Voici des exemples de fichiers .htaccess qui peuvent être créés à la racine du site.
Pour le header :
Code : Tout sélectionner
<IfModule mod_headers>
# Mise en cache pour un mois
<FilesMatch ".(ico|jpe?g|png|gif|swf|flv|gz)$">
Header set Cache-Control "max-age=2592000"
</FilesMatch>
# Mise en cache pour 2 heures
<filesMatch ".(css|js)$">
Header set Cache-Control "max-age=7200"
</filesMatch>
# Désactive la mise en cache
<FilesMatch ".(pl|php|cgi)$">
Header unset Cache-Control
</FilesMatch>
</IfModule>
Si module gzip :
Code : Tout sélectionner
<IfModule mod_gzip.c>
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_add_header_count Yes
mod_gzip_send_vary Yes
mod_gzip_item_exclude reqheader "User-agent: Mozilla/4.0[678]"
mod_gzip_item_include file .(html?|xml|txt|css|js)$
mod_gzip_item_include handler ^cgi-script$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/x-javascript.*
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</IfModule>
Code : Tout sélectionner
<IfModule mod_deflate>
# Compression avec MOD_DEFLATE
AddOutputFilterByType DEFLATE text/html text/css text/plain text/xml text/javascript application/x-javascript application/x-httpd-php
#Pour les navigateurs incompatibles
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4.0[678] no-gzip
BrowserMatch bMSIE !no-gzip !gzip-only-text/html
BrowserMatch bMSI[E] !no-gzip !gzip-only-text/html
# Les proxies ne doivent pas décompresser à la place de l'internaute
Header append Vary User-Agent env=!dont-vary
</IfModule>
Pour gérer les délai :
Code : Tout sélectionner
<IfModule mod_expires>
ExpiresActive On
ExpiresDefault "access plus 7200 seconds"
AddType image/x-icon .ico
ExpiresByType image/gif "access plus 2592000 seconds"
ExpiresByType image/ico "access plus 2592000 seconds"
ExpiresByType image/jpg "access plus 2592000 seconds"
ExpiresByType image/png "access plus 2592000 seconds"
ExpiresByType image/jpeg "access plus 2592000 seconds"
ExpiresByType image/icon "access plus 2592000 seconds"
ExpiresByType image/x-icon "access plus 2592000 seconds"
ExpiresByType text/css "access plus 2592000 seconds"
ExpiresByType text/html "access plus 7200 seconds"
ExpiresByType text/javascript "access plus 2592000 seconds"
ExpiresByType application/xhtml+xml "access plus 7200 seconds"
ExpiresByType application/x-javascript "access plus 2592000 seconds"
ExpiresByType application/x-shockwave-flash "access plus 2592000 seconds"
</IfModule>
Vous pouvez aussi installer un serveur de cache en front comme Varnish.
Optimiser MySQL
La théorie est la même que pour Apache, vous devez configurer MySQL selon les besoins en adéquation avec la mémoire disponible. Il existe deux scripts qui peuvent vous aider à optimiser MySQL.
- MySQL Tuning Primer Script : https://launchpad.net/mysql-tuning-primer
- MySQLTuner-perl : https://github.com/major/MySQLTuner-perl


Une optimisation MySQL peux être nécessaire de temps à autre :
Deux autres scripts vous permettent de monitorer l'activité MySQL :mysqlcheck -o --all-databases -u root -p
- Mytop : http://jeremy.zawodny.com/mysql/mytop/ ou https://github.com/jzawodn/mytop
- MySQLreport : http://hackmysql.com/mysqlreport


Pour identifier les requêtes qui sont trop longues (mal optimisées etc), vous devez activer le slow-log (qu'il convient de désactiver par la suite, puisque cela fera des accès disque) :
Vous devez ajouter/modifier le paramètre :
Relancez MySQL :log-slow-queries = /var/log/mysql/mysql-slow.log
Tester le serveur WEB/etc/init.d/mysql restart
Vous pouvez ensuite tester les réponses du serveur WEB.
Il existe beaucoup de programmes notamment ab (package apache2-utils sur Debian).
Exemple :
On obtient :ab -n 300 -c 30 http://www.serveur.com/page.php
Vous devez vérifier que vous n'avez pas d'erreur (Failed requests).Document Path: /index.php
Document Length: 281 bytes
Concurrency Level: 30
Time taken for tests: 1.791 seconds
Complete requests: 300
Failed requests: 0
Write errors: 0
Non-2xx responses: 300
Total transferred: 133500 bytes
HTML transferred: 84300 bytes
Requests per second: 167.53 [#/sec] (mean)
Time per request: 179.075 [ms] (mean)
Time per request: 5.969 [ms] (mean, across all concurrent requests)
Transfer rate: 72.80 [Kbytes/sec] received
Pour le taux de réponse ce qui est important sont les lignes :
ConclusionTime per request: 179.075 [ms] (mean)
Time per request: 5.969 [ms] (mean, across all concurrent requests)
Une bonne configuration permet de répondre au pic de demandes... une mauvaise configuration permettra le serveur à genoux. La limitation de charge reste la capacité hardware de votre serveur, notamment en mémoire.
Lire : [réseau] Sécuriser un serveur Apache/PHP/MySQL (LAMP)