Liste de contrôle essentielle pour l'optimisation des performances Nginx sur les sites à fort trafic
Une liste de contrôle pratique des performances Nginx pour les workers, connexions, tampons, mise en cache, compression, journaux, délais d'attente, TLS et fichiers statiques.
Liste de contrôle essentielle pour l'optimisation des performances Nginx sur les sites à fort trafic
L'optimisation des performances de Nginx est plus simple lorsqu'on la traite comme une liste de contrôle, et non comme un jeu de devinettes. Commencez par les limites qui déterminent la quantité de trafic que Nginx peut accepter, puis élargissez aux tampons, à la mise en cache, à la compression, à la journalisation, aux délais d'attente, à TLS et aux services backend qui se cachent derrière.
Ne copiez pas toutes les directives ici en production d'un coup. Une bonne liste de contrôle pour l'optimisation des performances de Nginx vous aide à décider quoi vérifier, pourquoi c'est important et ce qui peut mal tourner si vous en faites trop. Le réglage approprié pour un site de documentation principalement statique n'est pas le même que pour une API à long polling ou un service de téléchargement de fichiers.
1. Optimiser les processus workers et les connexions
Nginx utilise un modèle de processus maître-worker. Le processus maître lit la configuration et gère les processus workers, qui traitent les requêtes clients réelles. Configurer correctement ces éléments peut considérablement améliorer la concurrence et l'utilisation des ressources.
worker_processes
Cette directive détermine le nombre de processus workers que Nginx va générer. En général, le définir sur auto permet à Nginx de détecter le nombre de cœurs CPU et de générer un nombre égal de processus workers, ce qui est une bonne pratique courante.
worker_connections
Définit le nombre maximum de connexions simultanées qu'un seul processus worker peut ouvrir. Ce paramètre, combiné à worker_processes, détermine le nombre total théorique de connexions simultanées que Nginx peut gérer (worker_processes * worker_connections).
multi_accept
Permet à un processus worker d'accepter plusieurs nouvelles connexions à la fois, évitant ainsi les goulots d'étranglement potentiels sous forte charge.
# /etc/nginx/nginx.conf
worker_processes auto; # Généralement défini sur 'auto' ou le nombre de cœurs CPU
events {
worker_connections 1024; # Ajuster en fonction de la capacité du serveur et de la charge attendue
multi_accept on;
}
Astuce : Si le CPU est constamment élevé, augmenter
worker_connectionsne résoudra pas le problème tout seul. Vérifiez d'abord si le CPU provient des poignées de main TLS, de la compression, de la journalisation, du routage basé sur des expressions régulières ou de l'application en amont.
2. Gestion efficace des connexions
Optimiser la façon dont Nginx gère les connexions réseau peut réduire les frais généraux et améliorer la réactivité.
keepalive_timeout
Spécifie combien de temps une connexion keep-alive client reste ouverte. Réutiliser les connexions réduit les frais généraux liés à l'établissement de nouvelles connexions TCP et aux poignées de main SSL. Une valeur courante est de 15 à 65 secondes, selon l'interactivité de votre application.
sendfile
Permet le transfert direct de données entre les descripteurs de fichiers, contournant la mise en tampon dans l'espace utilisateur. Cela améliore considérablement les performances lors du service de fichiers statiques.
tcp_nopush
Fonctionne avec sendfile. Nginx essaie d'envoyer l'en-tête HTTP et le début du fichier dans un seul paquet. Ensuite, il envoie les données en paquets complets. Cela réduit le nombre de paquets envoyés.
tcp_nodelay
Ordonne à Nginx d'envoyer les données dès qu'elles sont disponibles, sans mise en tampon. Ceci est bénéfique pour les applications interactives où une faible latence est plus critique que la maximisation du débit (par exemple, les applications de chat ou les mises à jour en temps réel).
http {
keepalive_timeout 65; # Connexions keep-alive pendant 65 secondes
sendfile on;
tcp_nopush on; # Nécessite sendfile activé
tcp_nodelay on; # Utile pour le proxy de contenu dynamique
}
3. Optimisation des tampons
Nginx utilise des tampons pour gérer les requêtes clients et les réponses des serveurs en amont (comme les serveurs d'application). Dimensionner correctement ces tampons peut éviter les entrées/sorties disque inutiles, réduire l'utilisation de la mémoire et améliorer le débit.
Tampons clients
client_body_buffer_size: Taille du tampon pour le corps des requêtes clients. Si un corps dépasse cette taille, il est écrit dans un fichier temporaire.client_header_buffer_size: Taille du tampon pour la première ligne et les en-têtes d'une requête client.large_client_header_buffers: Définit le nombre et la taille des tampons plus grands pour lire les en-têtes des requêtes clients. Utile pour les requêtes avec de nombreux cookies ou des en-têtes referer longs.
Tampons proxy (pour les configurations de proxy inverse)
proxy_buffers: Le nombre et la taille des tampons utilisés pour lire les réponses du serveur proxy.proxy_buffer_size: La taille du premier tampon pour lire la réponse. Généralement plus petit, car il ne contient souvent que les en-têtes.proxy_busy_buffers_size: La quantité maximale de tampons de réponse pouvant être dans l'état 'occupé' (en cours d'envoi au client) à un moment donné.
Tampons FastCGI (pour PHP-FPM, etc.)
fastcgi_buffers: Le nombre et la taille des tampons utilisés pour lire les réponses du serveur FastCGI.fastcgi_buffer_size: La taille du premier tampon pour lire la réponse.
http {
# Tampons clients
client_body_buffer_size 1M; # Ajuster en fonction de la taille attendue du corps de la requête (ex. téléchargements de fichiers)
client_header_buffer_size 1k;
large_client_header_buffers 4 8k; # 4 tampons, chacun de 8 Ko
# Tampons proxy (si Nginx agit comme proxy inverse)
proxy_buffers 8 16k; # 8 tampons, chacun de 16 Ko
proxy_buffer_size 16k; # Premier tampon de 16 Ko
proxy_busy_buffers_size 16k; # Max 16 Ko de tampons occupés
# Tampons FastCGI (si Nginx fonctionne avec PHP-FPM)
fastcgi_buffers 16 16k; # Point de départ pour de nombreuses applications PHP-FPM
fastcgi_buffer_size 16k; # Premier tampon de 16 Ko
}
Attention : Définir des tampons trop petits peut entraîner des entrées/sorties disque et une dégradation des performances. Les définir trop grands peut consommer une mémoire excessive. Trouvez un équilibre par des tests.
4. Mettre en œuvre des stratégies de mise en cache robustes
La mise en cache est l'un des moyens les plus efficaces d'améliorer les performances et de réduire la charge sur vos serveurs backend. Nginx peut servir de puissant cache de contenu.
proxy_cache_path
Définit le chemin du répertoire de cache, sa taille, le nombre de niveaux de sous-répertoires et la durée de conservation des éléments inactifs dans le cache.
proxy_cache
Active la mise en cache pour un bloc location donné, en référençant la zone définie dans proxy_cache_path.
proxy_cache_valid
Définit la durée pendant laquelle Nginx doit mettre en cache les réponses avec des codes d'état HTTP spécifiques.
proxy_cache_revalidate
Lorsqu'il est activé, Nginx utilise les en-têtes If-Modified-Since et If-None-Match pour revalider le contenu mis en cache avec le backend, réduisant ainsi l'utilisation de la bande passante.
proxy_cache_use_stale
Ordonne à Nginx de servir le contenu mis en cache obsolète si le serveur backend est en panne, ne répond pas ou rencontre des erreurs. Cela améliore considérablement la disponibilité.
expires
Définit les en-têtes Cache-Control et Expires pour la mise en cache côté client des fichiers statiques. Cela minimise les requêtes répétées à Nginx.
http {
# Définir une zone de cache proxy dans le bloc http
proxy_cache_path /var/cache/nginx/my_cache levels=1:2 keys_zone=my_cache:10m inactive=60m max_size=10g;
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://my_upstream_backend;
proxy_cache my_cache; # Activer la mise en cache pour cet emplacement
proxy_cache_valid 200 302 10m; # Mettre en cache les réponses réussies pendant 10 minutes
proxy_cache_valid 404 1m; # Mettre en cache les 404 pendant 1 minute
proxy_cache_revalidate on;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
add_header X-Cache-Status $upstream_cache_status; # Aide au débogage
}
# Mettre en cache les fichiers statiques dans le navigateur pour une période plus longue
location ~* \.(jpg|jpeg|gif|png|css|js|ico|woff|woff2|ttf|svg|eot)$ {
expires 30d; # Mettre en cache pendant 30 jours
add_header Cache-Control "public, no-transform";
# Pour les fichiers statiques, envisagez de servir directement depuis Nginx s'ils ne sont pas proxy
root /var/www/html;
}
}
}
5. Activer la compression Gzip
Compresser les réponses avant de les envoyer aux clients peut réduire considérablement l'utilisation de la bande passante et améliorer les temps de chargement des pages, en particulier pour le contenu textuel.
gzip on
Active la compression gzip.
gzip_comp_level
Définit le niveau de compression (1-9). Le niveau 1 est le plus rapide avec moins de compression ; le niveau 9 est le plus lent avec une compression maximale. Le niveau 6 offre généralement un bon équilibre.
gzip_types
Spécifie les types MIME qui doivent être compressés. Incluez les types courants de texte, CSS, JavaScript et JSON.
gzip_min_length
Définit la longueur minimale d'une réponse (en octets) pour laquelle la compression doit être activée. Les petits fichiers ne bénéficient pas beaucoup de la compression et peuvent même être plus lents en raison des frais généraux de compression.
gzip_proxied
Ordonne à Nginx de compresser les réponses même si elles sont proxy. any est une valeur courante.
gzip_vary
Ajoute l'en-tête Vary: Accept-Encoding aux réponses, informant les proxies que la réponse peut différer en fonction de l'en-tête de requête Accept-Encoding.
http {
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6; # Niveau de compression 1-9 (6 est un bon équilibre)
gzip_buffers 16 8k; # 16 tampons, chacun de 8 Ko
gzip_http_version 1.1; # Version HTTP minimale pour la compression
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
gzip_min_length 1000; # Compresser uniquement les réponses de plus de 1 Ko
}
6. Optimiser la journalisation
Bien que les journaux soient essentiels pour la surveillance et le dépannage, une journalisation excessive ou non optimisée peut introduire des entrées/sorties disque importantes, en particulier sur les sites à fort trafic.
access_log
- Désactiver pour les actifs statiques : Pour le contenu statique très consulté (images, CSS, JS), désactiver
access_logpeut économiser beaucoup d'entrées/sorties. - Mise en tampon : Nginx peut mettre en mémoire tampon les entrées de journal avant de les écrire sur le disque, réduisant ainsi la fréquence des écritures disque. Les paramètres
bufferetflushsont utilisés ici.
error_log
Définissez le niveau de journalisation approprié (crit, error, warn, info, debug). Pour la production, warn ou error est généralement suffisant pour capturer les problèmes critiques sans inonder les journaux.
http {
server {
# Journal d'accès par défaut pour le contenu dynamique
access_log /var/log/nginx/access.log main;
location ~* \.(jpg|jpeg|gif|png|css|js|ico|woff|woff2|ttf|svg|eot)$ {
access_log off; # Désactiver la journalisation pour les fichiers statiques courants
expires 30d;
}
}
# Exemple de journal d'accès tamponné pour le contexte HTTP principal
# access_log /var/log/nginx/access.log main buffer=16k flush=5s;
error_log /var/log/nginx/error.log warn; # Journaliser uniquement les avertissements et les erreurs
}
7. Ajuster les délais d'attente
Des délais d'attente correctement configurés empêchent Nginx de conserver trop longtemps les connexions inactives, libérant ainsi des ressources.
Délais d'attente côté client
client_body_timeout: Combien de temps Nginx attend qu'un client envoie le corps de la requête.client_header_timeout: Combien de temps Nginx attend qu'un client envoie l'en-tête de la requête.send_timeout: Combien de temps Nginx attend qu'un client accepte la réponse après son envoi.
Délais d'attente proxy/FastCGI (le cas échéant)
proxy_connect_timeout: Délai d'attente pour établir une connexion avec un serveur proxy.proxy_send_timeout: Délai d'attente pour transmettre une requête au serveur proxy.proxy_read_timeout: Délai d'attente pour lire une réponse du serveur proxy.
http {
client_body_timeout 15s; # Le client a 15 secondes pour envoyer le corps
client_header_timeout 15s; # Le client a 15 secondes pour envoyer les en-têtes
send_timeout 15s; # Nginx a 15 secondes pour envoyer la réponse au client
# Pour les scénarios proxy
proxy_connect_timeout 5s; # 5 secondes pour se connecter à l'amont
proxy_send_timeout 15s; # 15 secondes pour envoyer la requête à l'amont
proxy_read_timeout 15s; # 15 secondes pour lire la réponse de l'amont
# Pour les scénarios FastCGI
fastcgi_connect_timeout 5s;
fastcgi_send_timeout 15s;
fastcgi_read_timeout 15s;
}
8. Optimisation SSL/TLS
Pour les sites activés HTTPS, l'optimisation des paramètres SSL/TLS est cruciale pour réduire la charge CPU et améliorer les performances des poignées de main.
ssl_session_cache et ssl_session_timeout
Activez la mise en cache des sessions SSL pour éviter la poignée de main TLS complète, coûteuse en calcul, pour les connexions suivantes du même client.
ssl_protocols et ssl_ciphers
Utilisez des protocoles TLS modernes comme TLSv1.2 et TLSv1.3. Soyez prudent avec les chaînes de chiffrement copiées : les chiffrements TLS 1.3 ne sont pas contrôlés de la même manière que les suites de chiffrement TLS plus anciennes, et les valeurs par défaut de la distribution sont souvent plus sûres que des exemples obsolètes provenant d'anciens guides.
ssl_stapling
Active l'agrafage OCSP, où Nginx récupère périodiquement la réponse OCSP de l'autorité de certification et l'"agrafe" à la poignée de main SSL/TLS. Cela réduit la latence côté client en évitant une requête OCSP distincte.
server {
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/your_domain.crt;
ssl_certificate_key /etc/nginx/ssl/your_domain.key;
ssl_session_cache shared:SSL:10m; # Cache partagé pour 10 Mo de données de session
ssl_session_timeout 10m; # Les sessions expirent après 10 minutes
ssl_protocols TLSv1.2 TLSv1.3; # Utiliser des protocoles modernes et sécurisés
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 8.8.8.8 valid=300s; # Utiliser des résolveurs approuvés pour votre environnement
resolver_timeout 5s;
}
9. Cache des fichiers ouverts
Nginx peut mettre en cache les descripteurs de fichiers pour les fichiers fréquemment consultés, réduisant ainsi le besoin d'appels système répétés pour ouvrir et fermer des fichiers.
open_file_cache
Active le cache, en spécifiant le nombre maximum d'éléments et la durée de conservation des éléments inactifs.
open_file_cache_valid
Définit la fréquence à laquelle le cache doit vérifier la validité de ses éléments.
open_file_cache_min_uses
Spécifie le nombre minimum de fois qu'un fichier doit être consulté pendant la période inactive pour rester dans le cache.
open_file_cache_errors
Détermine si Nginx doit mettre en cache les erreurs lors de l'ouverture de fichiers.
http {
open_file_cache max=100000 inactive=60s; # Mettre en cache jusqu'à 100 000 descripteurs de fichiers pendant 60s
open_file_cache_valid 80s; # Vérifier la validité toutes les 80 secondes
open_file_cache_min_uses 1; # Mettre en cache les fichiers utilisés au moins une fois
open_file_cache_errors on; # Mettre en cache les erreurs liées à l'ouverture de fichiers
}
10. Valider avec des signaux de trafic réels
Le dernier élément de la liste de contrôle est la mesure. Avant un changement, capturez une petite référence : latence des requêtes, taux de 5xx, connexions actives, CPU, mémoire, entrées/sorties disque, débit réseau et temps de réponse en amont. Après le changement, comparez les mêmes chiffres.
Pour un proxy inverse, $request_time et $upstream_response_time sont particulièrement utiles. Si les deux augmentent ensemble, le backend est probablement lent. Si $request_time est élevé alors que le temps en amont est faible ou vide, examinez la vitesse de téléchargement du client, le temps de transfert de la réponse, la mise en tampon, la compression ou la livraison de fichiers statiques. Si aucune métrique n'explique le problème, vérifiez le journal des erreurs et le système d'exploitation.
La séquence de réglage la plus sûre est simple : testez la configuration avec nginx -t, rechargez plutôt que redémarrez lorsque c'est possible, surveillez les journaux et revenez en arrière rapidement si la latence ou les erreurs évoluent dans la mauvaise direction. Nginx peut gérer beaucoup de trafic, mais seulement lorsque ses limites, le noyau et l'application en amont sont en accord les uns avec les autres.