Surcharge serveur
Quand votre serveur ne tient plus la charge
CPU à 100%, RAM saturée, files d’attente qui explosent : identifiez et résolvez.
Les symptômes typiques
Vous êtes probablement face à une surcharge serveur si :
- Le site était lent avant de tomber (pas une coupure brutale)
- Les erreurs 503 sont intermittentes (ça marche, puis non, puis oui…)
- Vous avez eu un pic de trafic récent (campagne, article viral, promo)
- Le serveur répond très lentement même en SSH
- Les fichiers statiques (images, CSS) chargent mais pas les pages PHP
Une surcharge n’est pas une panne : votre serveur fonctionne, il est juste submergé. La bonne nouvelle : c’est généralement réversible rapidement.
Diagnostic en 5 commandes
Connectez-vous en SSH et exécutez ces commandes :
1. Load average (charge globale)
$ uptime
14:32:01 up 45 days, load average: 12.50, 8.30, 4.20
│ │ │
│ │ └─ Moyenne 15 min
│ └─ Moyenne 5 min
└─ Moyenne 1 min
# Règle : load average > nombre de CPU = surcharge
$ nproc
4
# Ici : 12.50 > 4 = serveur surchargé (3x la capacité)
| Load / CPU | État | Action |
|---|---|---|
| < 1 | ✅ Tranquille | Rien à faire |
| 1 – 2 | ⚠️ Chargé | Surveiller |
| 2 – 4 | ?? Surcharge | Investiguer |
| > 4 | ?? Critique | Action immédiate |
2. Utilisation CPU et RAM
$ top -bn1 | head -20
top - 14:32:01 up 45 days, 4 users, load average: 12.50, 8.30, 4.20
Tasks: 203 total, 15 running, 188 sleeping, 0 stopped, 0 zombie
%Cpu(s): 94.2 us, 3.1 sy, 0.0 ni, 2.1 id, 0.3 wa, 0.0 hi, 0.3 si
MiB Mem : 16384.0 total, 512.3 free, 14821.2 used, 1050.5 buff/cache
MiB Swap: 4096.0 total, 1024.0 free, 3072.0 used. 892.1 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
15234 www-data 20 0 512340 245612 8432 R 89.3 1.5 12:34.56 php-fpm
15235 www-data 20 0 498220 231004 8124 R 78.2 1.4 11:22.33 php-fpm
15236 www-data 20 0 501832 238456 8256 R 72.1 1.5 10:45.12 php-fpm
Ce qu’il faut regarder :
%Cpu(s): 94.2 us→ 94% CPU utilisé (??)MiB Mem: 512.3 free→ Seulement 512 Mo libres (??)php-fpmen tête → Ce sont les workers PHP qui consomment
3. Qui consomme quoi ?
# Top 10 processus par CPU
$ ps aux --sort=-%cpu | head -10
# Top 10 processus par RAM
$ ps aux --sort=-%mem | head -10
# Nombre de processus PHP actifs
$ ps aux | grep php-fpm | wc -l
48
# Nombre de connexions HTTP actives
$ ss -tuln | grep -E ':(80|443)' | wc -l
1247
4. État de PHP-FPM
$ systemctl status php8.2-fpm
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
Active: active (running)
Main PID: 1234
Status: "Processes active: 50, idle: 0, Requests: 15234"
│
└─ 0 idle = tous les workers occupés !
# Logs PHP-FPM
$ tail -20 /var/log/php8.2-fpm.log
[WARNING] server reached pm.max_children setting (50), consider raising it
# ⚠️ Ce message = vous avez atteint la limite
5. Espace disque et I/O
# Espace disque
$ df -h
Filesystem Size Used Avail Use%
/dev/sda1 100G 98G 2G 98% # ?? Critique !
# Activité disque
$ iostat -x 1 3
Device r/s w/s await %util
sda 450.00 120.00 45.23 98.50 # ?? Disque saturé
Les 5 causes principales
Pic de trafic légitime
Situation : Campagne marketing, article viral, passage TV, Black Friday.
Diagnostic :
# Requêtes par seconde dans les logs
$ tail -10000 /var/log/nginx/access.log | awk '{print $4}' | cut -d: -f1-3 | uniq -c
250 26/Dec/2024:14:30
890 26/Dec/2024:14:31 # ← Pic brutal
920 26/Dec/2024:14:32
Solutions immédiates :
- Activer un cache agressif (page caching)
- Augmenter temporairement les ressources (scale up)
- Mettre en file d’attente les visiteurs (Cloudflare Waiting Room)
Bot agressif / Crawler
Situation : Un bot scanne votre site de façon intensive (SEO, scraping, indexation).
Diagnostic :
# Top 10 IPs par nombre de requêtes
$ awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
15234 185.191.171.44 # ← SemrushBot
8921 66.249.66.91 # ← Googlebot
7845 114.119.128.45 # ← Bot chinois suspect
Solutions immédiates :
# Bloquer une IP
$ iptables -A INPUT -s 114.119.128.45 -j DROP
# Ou dans Nginx
# deny 114.119.128.45;
# Limiter les bots via robots.txt
# User-agent: SemrushBot
# Crawl-delay: 10
Workers PHP insuffisants
Situation : Configuration PHP-FPM sous-dimensionnée pour le trafic.
Diagnostic :
$ grep -E "pm\.(max_children|start_servers|min_spare|max_spare)" /etc/php/8.2/fpm/pool.d/www.conf
pm.max_children = 5 # ← Beaucoup trop bas !
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
Solution : Augmenter pm.max_children selon votre RAM disponible.
; Règle : max_children = RAM disponible (Mo) / Mémoire par processus PHP (Mo)
; Exemple : 8 Go RAM, 128 Mo par process = 8000 / 128 = ~60
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
$ systemctl restart php8.2-fpm
Requêtes lentes / Boucles
Situation : Un script PHP tourne en boucle ou des requêtes SQL non optimisées bloquent.
Diagnostic :
# Requêtes PHP en cours depuis longtemps
$ ps aux | grep php | awk '$10 > "00:30" {print}'
# Slow queries MySQL
$ tail -50 /var/log/mysql/slow-query.log
# Processus MySQL actifs
$ mysql -e "SHOW PROCESSLIST;" | grep -v Sleep
Solutions :
- Identifier et optimiser la requête lente
- Ajouter des index MySQL manquants
- Killer les processus bloqués :
kill -9
Mémoire insuffisante (OOM)
Situation : Le serveur manque de RAM et le kernel tue des processus.
Diagnostic :
# Vérifier les OOM kills récents
$ dmesg | grep -i "out of memory"
$ grep -i "killed process" /var/log/syslog
# Utilisation swap
$ free -h
total used free
Mem: 8Gi 7.8Gi 200Mi
Swap: 4Gi 3.9Gi 100Mi # ← Swap presque plein = RAM saturée
Solutions :
- Augmenter la RAM (upgrade serveur)
- Réduire
pm.max_childrenPHP - Optimiser la consommation mémoire des applications
- Ajouter du swap temporairement
Solutions immédiates (urgence)
Quand le serveur est surchargé et que le site est down, voici les actions rapides :
Action 1 : Identifier et killer les processus gourmands
# Identifier
$ top -bn1 | head -15
# Killer un processus spécifique
$ kill -9 <PID>
# Killer tous les processus PHP (attention !)
$ pkill -9 php-fpm
$ systemctl restart php8.2-fpm
Action 2 : Bloquer le trafic suspect
# Bloquer une IP agressive
$ iptables -A INPUT -s <IP_SUSPECTE> -j DROP
# Bloquer un range
$ iptables -A INPUT -s 114.119.0.0/16 -j DROP
# Sauvegarder les règles
$ iptables-save > /etc/iptables.rules
Action 3 : Activer un mode dégradé
/etc/nginx/conf.d/emergency.conf
# Cache statique d'urgence
proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=emergency:10m max_size=1g;
server {
# ... config existante ...
location / {
# Servir depuis le cache si backend down
proxy_cache emergency;
proxy_cache_valid 200 5m;
proxy_cache_use_stale error timeout http_503;
# Limiter les connexions par IP
limit_conn addr 10;
limit_req zone=one burst=20 nodelay;
}
}
Action 4 : Activer la maintenance le temps de résoudre
# Activer la maintenance avec estimation
$ echo "3600" > /var/www/monsite/.maintenance
# Vérifier
$ curl -I https://monsite.com
HTTP/1.1 503 Service Unavailable
Retry-After: 3600
La maintenance vous donne le temps de diagnostiquer calmement sans que les visiteurs continuent d’affluer et d’aggraver la surcharge.
Optimisations long terme
Une fois l’urgence passée, mettez en place ces optimisations pour éviter que ça se reproduise :
Niveau 1 : Cache applicatif
WordPress
# Installer un plugin de cache
wp plugin install wp-super-cache --activate
# Ou Redis Object Cache
wp plugin install redis-cache --activate
wp redis enable
PrestaShop
# Activer le cache Smarty
# Back-office > Paramètres avancés > Performances
# Cache : Activer
# Type de cache : Système de fichiers
# Activer CCC (Combine, Compress, Cache)
Niveau 2 : Configuration PHP-FPM optimisée
/etc/php/8.2/fpm/pool.d/www.conf
; Configuration pour serveur 8 Go RAM
[www]
user = www-data
group = www-data
listen = /run/php/php8.2-fpm.sock
; Process Manager
pm = dynamic
pm.max_children = 50 ; RAM / ~150Mo par process
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500 ; Recycle les workers (évite memory leaks)
; Timeouts
request_terminate_timeout = 60s
request_slowlog_timeout = 10s
slowlog = /var/log/php-fpm/slow.log
; Status page (pour monitoring)
pm.status_path = /fpm-status
Niveau 3 : Configuration Nginx optimisée
/etc/nginx/nginx.conf
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
http {
# Buffers
client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 8m;
large_client_header_buffers 2 1k;
# Timeouts
client_body_timeout 12;
client_header_timeout 12;
keepalive_timeout 15;
send_timeout 10;
# Gzip
gzip on;
gzip_comp_level 5;
gzip_min_length 256;
gzip_types text/plain text/css application/json application/javascript;
# Rate limiting
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;
}
Niveau 4 : Mise en place d’un CDN
Un CDN (Cloudflare, Fastly, CloudFront) absorbe le trafic et protège votre serveur :
- Cache des fichiers statiques en edge
- Protection DDoS incluse
- Réduction de charge serveur de 50-80%
- Waiting Room pour les pics de trafic
Cloudflare propose un plan gratuit suffisant pour la plupart des sites. Pour une configuration avancée ou un CDN premium, Foxop peut vous accompagner.
Monitoring pour anticiper
Ne découvrez plus les surcharges par vos clients. Mettez en place une surveillance proactive :
Métriques à surveiller
| Métrique | Seuil warning | Seuil critique | Outil |
|---|---|---|---|
| Load average | > 2x CPU | > 4x CPU | Netdata, Prometheus |
| CPU % | > 80% | > 95% | top, Grafana |
| RAM % | > 85% | > 95% | free, Grafana |
| Workers PHP idle | < 5 | 0 | PHP-FPM status |
| Temps réponse | > 2s | > 5s | Uptime monitoring |
| Requêtes/seconde | Variable | +200% normal | Access logs |
Script de surveillance simple
/usr/local/bin/check-load.sh
#!/bin/bash
# Alerte si load average trop élevé
THRESHOLD=4
LOAD=$(uptime | awk -F'load average:' '{print $2}' | cut -d, -f1 | tr -d ' ')
LOAD_INT=${LOAD%.*}
if [ "$LOAD_INT" -gt "$THRESHOLD" ]; then
echo "⚠️ ALERTE: Load average à $LOAD (seuil: $THRESHOLD)" | \
mail -s "[URGENT] Surcharge serveur monsite.com" [email protected]
fi
# Ajouter au cron (toutes les 5 min)
$ crontab -e
*/5 * * * * /usr/local/bin/check-load.sh
Surveillance proactive 24/7
Alertes instantanées, diagnostic automatique, estimation de capacité.
Questions fréquentes
Comment calculer le bon nombre de workers PHP ?
Formule simple : max_children = RAM disponible (Mo) / Mémoire moyenne par process PHP. Pour connaître la mémoire par process : ps --no-headers -o rss -C php-fpm | awk '{sum+=$1} END {print sum/NR/1024 " Mo"}'. Avec 8 Go de RAM et 150 Mo par process, vous pouvez avoir environ 50 workers.
Le load average est élevé mais le CPU est bas, pourquoi ?
Le load average compte tous les processus en attente, pas seulement CPU. Un load élevé avec CPU bas indique souvent des I/O wait (disque lent, NFS, base de données externe). Vérifiez avec iostat -x 1 ou regardez %wa dans top.
Dois-je augmenter la RAM ou le CPU ?
Analysez d’abord le goulot d’étranglement. Si la RAM est constamment > 90% avec du swap utilisé → ajoutez de la RAM. Si le CPU est > 90% mais la RAM OK → ajoutez du CPU ou optimisez le code. Souvent, ajouter de la RAM permet plus de workers PHP, ce qui résout les deux problèmes.
Comment gérer un pic de trafic prévu (Black Friday, lancement) ?
Préparez-vous : activez un CDN avec cache agressif, augmentez temporairement les ressources serveur (scale up), mettez en place une Waiting Room (Cloudflare), désactivez les fonctionnalités non essentielles, et surveillez en temps réel avec des alertes configurées.