Aller au contenu principal

Debug des performances serveur

Ce guide vous aide à identifier et résoudre les problèmes de performances sur votre VPS.

Diagnostic rapide

Vue d'ensemble avec htop

# Installer htop
sudo apt install htop

# Lancer
htop

Raccourcis htop :

  • F6 : Trier par CPU, RAM, etc.
  • F9 : Tuer un processus
  • F5 : Vue arborescente
  • q : Quitter

Indicateurs clés

# Charge système
uptime

# Résultat : load average: 0.50, 0.75, 0.60
# = charge sur 1min, 5min, 15min

Interprétation du load average (pour un VPS avec N coeurs) :

  • < N : Normal
  • = N : Utilisation maximale
  • N : Surcharge

# Voir le nombre de coeurs
nproc

Analyser l'utilisation CPU

Identifier les processus gourmands

# Top 10 par CPU
ps aux --sort=-%cpu | head -11

# En temps réel
top -o %CPU

CPU par processus dans le temps

# Surveiller un processus spécifique
pidstat -p PID 1

Profiler un service

# Installer perf
sudo apt install linux-tools-common linux-tools-$(uname -r)

# Profiler pendant 30 secondes
sudo perf top -p PID

Analyser l'utilisation mémoire

Vue d'ensemble

free -h
              total        used        free      shared  buff/cache   available
Mem: 3.8Gi 2.1Gi 200Mi 100Mi 1.5Gi 1.4Gi
Swap: 2.0Gi 500Mi 1.5Gi
  • available : Mémoire réellement utilisable
  • buff/cache : Cache système (libérable si nécessaire)

Détail par processus

# Top 10 par RAM
ps aux --sort=-%mem | head -11

# Avec plus de détails
ps aux --sort=-%mem | awk 'NR<=11{printf "%-10s %-8s %-8s %s\n", $1, $4"%", $6/1024"MB", $11}'

Fuites mémoire

# Surveiller la mémoire d'un processus dans le temps
watch -n 1 "ps -p PID -o pid,rss,vsz,pmem,comm"

Si la RAM augmente continuellement = fuite mémoire.

Swap utilisé

# Voir le swap par processus
for file in /proc/*/status ; do
awk '/VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file 2>/dev/null
done | sort -k 2 -n -r | head -10

Analyser les I/O disque

Vue d'ensemble

# Installer iotop
sudo apt install iotop

# Lancer
sudo iotop -o

Statistiques I/O

# Installer sysstat
sudo apt install sysstat

# Stats I/O toutes les secondes
iostat -x 1

Colonnes importantes :

  • %util : Utilisation du disque (>80% = goulot d'étranglement)
  • await : Temps d'attente I/O (>20ms = lent)
  • r/s, w/s : Lectures/écritures par seconde

Identifier les processus I/O

# Processus avec le plus d'I/O
sudo iotop -o -b -n 3

Analyser le réseau

Bande passante

# Installer iftop
sudo apt install iftop

# Surveiller
sudo iftop -i eth0

Connexions actives

# Nombre de connexions par état
ss -s

# Connexions établies
ss -tn state established

# Connexions par IP
ss -tn | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -10

Débit réseau

# Installer nload
sudo apt install nload

# Surveiller
nload eth0

Problèmes courants et solutions

CPU à 100%

Cause : Processus emballé

# Identifier
top -o %CPU

# Solution : Redémarrer le service
systemctl restart nom_du_service

# Ou tuer le processus (dernier recours)
kill -9 PID

Cause : Attaque ou spam

# Vérifier les connexions
ss -tn | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head

# Bloquer une IP
sudo ufw deny from IP_SUSPECTE

RAM saturée

Solution immédiate :

# Vider le cache (sans risque)
sync; echo 3 | sudo tee /proc/sys/vm/drop_caches

Solution long terme :

  • Augmenter le swap
  • Optimiser l'application
  • Upgrade le VPS

Disque I/O lent

Cause : Logs trop volumineux

# Identifier
du -h /var/log/ | sort -hr | head

# Nettoyer
sudo journalctl --vacuum-size=500M

Cause : Requêtes base de données

# Voir les requêtes lentes MySQL
sudo mysqladmin -u root -p processlist

Latence réseau

# Tester
ping -c 10 google.com
mtr google.com

Optimisations courantes

MySQL/MariaDB

sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
# Cache de requêtes
query_cache_type = 1
query_cache_size = 64M

# Buffers
innodb_buffer_pool_size = 512M
innodb_log_file_size = 128M

# Connexions
max_connections = 100

Nginx

sudo nano /etc/nginx/nginx.conf
worker_processes auto;
worker_connections 1024;

# Gzip
gzip on;
gzip_types text/plain text/css application/json application/javascript;

# Cache
open_file_cache max=1000 inactive=20s;

PHP-FPM

sudo nano /etc/php/8.1/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500

Paramètres système

sudo nano /etc/sysctl.d/99-performance.conf
# Réseau
net.core.somaxconn = 65535
net.ipv4.tcp_max_tw_buckets = 1440000
net.ipv4.tcp_fin_timeout = 15

# Fichiers
fs.file-max = 65535
sudo sysctl -p /etc/sysctl.d/99-performance.conf

Script de diagnostic complet

#!/bin/bash
# /usr/local/bin/diagnose.sh

echo "=== DIAGNOSTIC PERFORMANCES $(date) ==="
echo ""

echo "--- Système ---"
echo "OS: $(cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2)"
echo "Kernel: $(uname -r)"
echo "Uptime: $(uptime -p)"
echo "Load: $(uptime | awk -F'load average:' '{print $2}')"
echo ""

echo "--- CPU ---"
echo "Coeurs: $(nproc)"
echo "Top 5 CPU:"
ps aux --sort=-%cpu | head -6 | tail -5 | awk '{printf " %-20s %s%%\n", $11, $3}'
echo ""

echo "--- Mémoire ---"
free -h | grep -E "Mem|Swap"
echo "Top 5 RAM:"
ps aux --sort=-%mem | head -6 | tail -5 | awk '{printf " %-20s %s%%\n", $11, $4}'
echo ""

echo "--- Disque ---"
df -h | grep -E "^/dev"
echo ""

echo "--- Réseau ---"
echo "Connexions: $(ss -s | grep estab | awk '{print $4}' | cut -d, -f1)"
echo ""

echo "--- Services critiques ---"
for svc in nginx apache2 mysql mariadb php-fpm; do
if systemctl is-active --quiet $svc 2>/dev/null; then
echo " $svc: OK"
fi
done
echo ""

echo "=== FIN DIAGNOSTIC ==="
sudo chmod +x /usr/local/bin/diagnose.sh

Monitoring continu

Avec Netdata (recommandé)

# Installation
bash <(curl -Ss https://my-netdata.io/kickstart.sh)

# Accès : http://VOTRE_IP:19999

Alertes avec cron

#!/bin/bash
# /usr/local/bin/perf-alert.sh

# Seuils
CPU_THRESHOLD=80
MEM_THRESHOLD=85
DISK_THRESHOLD=90

# Vérification CPU (load average)
LOAD=$(uptime | awk -F'load average:' '{print $2}' | cut -d, -f1 | xargs)
CORES=$(nproc)
LOAD_PCT=$(echo "$LOAD $CORES" | awk '{printf "%.0f", ($1/$2)*100}')

# Vérification RAM
MEM_PCT=$(free | grep Mem | awk '{printf "%.0f", $3/$2 * 100}')

# Vérification Disque
DISK_PCT=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')

# Alertes
if [ $LOAD_PCT -gt $CPU_THRESHOLD ]; then
echo "ALERTE CPU: ${LOAD_PCT}%"
fi

if [ $MEM_PCT -gt $MEM_THRESHOLD ]; then
echo "ALERTE RAM: ${MEM_PCT}%"
fi

if [ $DISK_PCT -gt $DISK_THRESHOLD ]; then
echo "ALERTE DISQUE: ${DISK_PCT}%"
fi
Conseil

Pour un monitoring professionnel, consultez le guide Monitoring serveur.