Optimisation des processus de travail Nginx pour des performances maximales : Guide pratique
Optimisez votre serveur Nginx pour un trafic à fort volume grâce à ce guide pratique de configuration des directives de performance essentielles. Apprenez les meilleures pratiques pour définir `worker_processes` en fonction des cœurs CPU, maximiser la concurrence avec `worker_connections`, et assurer la conformité avec les limites de descripteurs de fichiers du système d'exploitation sous-jacent (`ulimit`). Cet article fournit des exemples de configuration concrets et des conseils d'optimisation indispensables pour minimiser la latence et augmenter considérablement le débit de votre serveur.
Optimisation des processus de travail Nginx pour des performances maximales : Guide pratique
Nginx peut gérer un grand nombre de connexions simultanées avec une faible empreinte de processus, mais seulement si ses limites de travail sont alignées sur la machine sous-jacente. Les deux paramètres auxquels on pense en premier sont worker_processes et worker_connections. Ils sont utiles, mais ils sont aussi faciles à sur-optimiser. Définir les deux à des nombres énormes ne crée pas de capacité gratuite. Cela peut simplement déplacer le goulot d'étranglement vers les descripteurs de fichiers, la mémoire, les serveurs en amont ou la pile réseau.
L'objectif pratique est de donner à Nginx suffisamment de travailleurs pour utiliser les cœurs CPU dont il dispose, suffisamment d'emplacements de connexion pour le trafic réel, et suffisamment de limites du système d'exploitation pour éviter d'atteindre le plafond lors des pics normaux.
Comprendre l'architecture des travailleurs Nginx
Nginx fonctionne selon un modèle maître-travailleur. Le Processus Maître est responsable de la lecture et de la validation de la configuration, de la liaison aux ports et de la gestion des processus de travail. Il effectue des tâches non critiques comme la surveillance des ressources système et le redémarrage des travailleurs si nécessaire.
Les Processus de Travail sont là où le gros du travail est effectué. Ces processus sont monothreadés (dans la compilation standard de Nginx) et utilisent des appels système non bloquants. Chaque travailleur gère des milliers de connexions simultanées efficacement en utilisant une boucle d'événements, permettant à un processus de gérer plusieurs requêtes sans blocage, ce qui est essentiel aux performances de Nginx.
Une optimisation appropriée implique d'équilibrer le nombre de travailleurs (en les liant aux ressources CPU) et de définir le nombre maximum de connexions que chaque travailleur peut gérer.
Configuration de worker_processes : Le facteur cœurs CPU
La directive worker_processes détermine combien de processus de travail Nginx doit créer. Ce paramètre affecte directement la façon dont Nginx utilise les ressources CPU de votre serveur.
Meilleure pratique : Faire correspondre les travailleurs aux cœurs
La meilleure pratique la plus courante et la plus recommandée est de définir le nombre de processus de travail égal au nombre de cœurs CPU disponibles sur votre serveur. Cela garantit que chaque cœur est utilisé efficacement sans encourir de surcharge excessive due aux changements de contexte.
Si le nombre de travailleurs dépasse le nombre de cœurs, le système d'exploitation doit fréquemment basculer le focus CPU entre les processus Nginx concurrents (changement de contexte), ce qui introduit de la latence et réduit les performances globales.
Utilisation de la directive auto
Pour les versions modernes de Nginx (1.3.8 et ultérieures), la configuration la plus simple et la plus efficace consiste à utiliser le paramètre auto. Nginx détectera automatiquement le nombre de cœurs CPU disponibles et définira les processus de travail en conséquence.
# Paramètre recommandé pour la plupart des déploiements
worker_processes auto;
Configuration manuelle
Si vous avez besoin d'un contrôle manuel ou utilisez une version plus ancienne, vous pouvez spécifier le nombre exact de travailleurs. Vous pouvez trouver le nombre de cœurs à l'aide des utilitaires système :
# Trouver le nombre de cœurs CPU
grep processor /proc/cpuinfo | wc -l
Si le système a 8 cœurs, la configuration ressemblerait à ceci :
# Définition manuelle des processus de travail à 8
worker_processes 8;
Astuce : Faire correspondre le nombre de cœurs disponibles est le point de départ le plus sûr. Dans des charges de travail inhabituelles avec beaucoup d'E/S, vous pouvez tester une valeur différente, mais évaluez-la sous un trafic réaliste avant de la conserver. Pour le service statique typique, le proxy et la terminaison TLS,
autoest généralement le choix le moins surprenant.
Configuration de worker_connections : Le facteur de concurrence
La directive worker_connections est configurée dans le bloc events et définit le nombre maximum de connexions simultanées qu'un seul processus de travail peut gérer. Cela inclut les connexions aux clients, les connexions aux serveurs proxy en amont et les connexions internes de vérification de santé.
Calcul du nombre maximum de clients
Le nombre théorique maximum de connexions client simultanées que votre serveur Nginx peut gérer est calculé comme suit :
$$\text{Max Clients} = \text{worker_processes} \times \text{worker_connections}$$
Si vous avez 4 processus de travail et 10 000 connexions de travail par processus, Nginx pourrait théoriquement gérer 40 000 connexions simultanées.
Ce nombre n'est qu'une limite supérieure approximative. Une requête proxy peut utiliser une connexion client et une connexion amont en même temps. Le trafic WebSocket et long-polling peut occuper des emplacements beaucoup plus longtemps qu'une requête de page normale. Les connexions persistantes (keep-alive) peuvent également rester ouvertes tout en effectuant très peu de travail. Si Nginx sert principalement des fichiers statiques, le calcul est plus proche de la formule simple. S'il agit comme un proxy inverse, laissez une marge.
Définition de la limite de connexion
Il est courant de définir worker_connections à quelques milliers ou plus sur des serveurs occupés, en supposant que les limites de mémoire et de descripteurs de fichiers peuvent le supporter. Ne copiez pas une grande valeur aveuglément ; choisissez une valeur qui correspond à la concurrence attendue plus une marge pour les pics.
# Exemple de configuration pour le bloc events
events {
# Connexions simultanées max par processus de travail
worker_connections 16384;
# Peut aider lors des pics, mais testez l'équité sous charge.
multi_accept on;
}
Contrainte des limites système (ulimit)
Crucialement, le paramètre worker_connections est contraint par la limite du système d'exploitation sur le nombre de descripteurs de fichiers (FD) autorisés par processus, souvent contrôlé par le paramètre ulimit -n.
Nginx ne peut pas ouvrir plus de connexions que le système d'exploitation n'autorise de descripteurs de fichiers. Étant donné que chaque connexion (socket client, fichier journal, socket proxy) nécessite un descripteur de fichier, il est essentiel que la limite système soit définie suffisamment haute.
Vérification et augmentation des limites de descripteurs de fichiers
Vérifiez la limite actuelle :
ulimit -nAugmentez temporairement la limite (pour la session en cours) :
ulimit -n 65536Augmentez la limite de manière permanente (via
/etc/security/limits.conf) :Ajoutez les lignes suivantes, en remplaçant
nginx_userpar l'utilisateur sous lequel Nginx s'exécute (souventwww-dataounginx) :# /etc/security/limits.conf nginx_user soft nofile 65536 nginx_user hard nofile 65536
Attention : Assurez-vous que la limite de descripteurs de fichiers par processus pour l'utilisateur du travailleur Nginx est supérieure à
worker_connections, avec une marge supplémentaire pour les journaux, les sockets en amont, les fichiers cache et autres fichiers ouverts. Les limites à l'échelle du système comptent aussi, mais la limite par processus est celle qui surprend le plus souvent les gens.
Si Nginx est géré par systemd, /etc/security/limits.conf peut ne pas suffire. De nombreuses distributions démarrent les services avec des limites provenant du fichier unité. Vérifiez la limite active avec :
cat /proc/$(pgrep -o nginx)/limits | grep "open files"
Pour une substitution systemd, utilisez :
sudo systemctl edit nginx
Ajoutez ensuite :
[Service]
LimitNOFILE=65536
Rechargez systemd et redémarrez Nginx pendant une fenêtre de maintenance :
sudo systemctl daemon-reload
sudo systemctl restart nginx
Réglage avancé et surveillance
Au-delà des directives de base, quelques considérations supplémentaires peuvent aider à affiner les performances :
1. Épinglage des processus de travail
Dans les environnements hautes performances, en particulier sur les systèmes avec plusieurs sockets CPU (architectures NUMA), vous pouvez utiliser la directive worker_cpu_affinity. Cela indique au système d'exploitation de restreindre des processus de travail spécifiques à des CPU spécifiques, ce qui peut améliorer les performances en garantissant que les caches CPU restent chauds et en évitant les problèmes de localité mémoire.
Exemple pour un système à 8 cœurs :
worker_processes 8;
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
Ce paramètre est complexe et généralement bénéfique uniquement pour des situations de charge extrême ; worker_processes auto est suffisant pour la plupart des déploiements.
2. Surveillance des métriques de performance
Après avoir appliqué des optimisations, il est crucial de surveiller l'impact. Utilisez le module Nginx Stub Status (ou un outil comme Prometheus/Grafana) pour suivre les métriques clés :
| Métrique | Description | Vérification d'optimisation |
|---|---|---|
| Connexions actives | Total des connexions actuellement gérées. | Devrait être inférieur au max théorique. |
| Lecture/Écriture/Attente | Connexions dans différents états. | Un nombre élevé d'Attente indique souvent des Keep-Alives HTTP de longue durée (bon) ou des ressources de traitement insuffisantes (mauvais). |
| Taux de requêtes | Requêtes par seconde. | Utilisé pour mesurer l'amélioration réelle des performances après les changements de configuration. |
Si vous observez une utilisation CPU élevée sur tous les cœurs et des taux de requêtes élevés, vos worker_processes sont probablement configurés correctement. Si vous avez des cœurs CPU inactifs pendant le trafic de pointe, envisagez de revoir votre configuration ou de vérifier les opérations d'E/S bloquantes en dehors de Nginx.
3. Stratégie de débordement de connexion
Si le serveur atteint la limite maximale de connexions (worker_processes * worker_connections), les nouvelles connexions peuvent échouer ou rester dans des files d'attente jusqu'à leur expiration. Augmenter worker_connections ne peut aider que lorsque Nginx est le véritable goulot d'étranglement. Si les serveurs d'application en amont sont saturés, augmenter la limite peut empirer la panne car plus de requêtes s'accumulent derrière des backends lents.
Utilisez le journal des erreurs comme signal. Des messages comme worker_connections are not enough pointent directement vers les limites de Nginx. Une augmentation des messages upstream timed out, connect() failed ou des réponses 502/504 pointe davantage vers la capacité du backend, les problèmes réseau ou les paramètres de délai d'attente.
Une configuration de départ raisonnable
Pour un petit ou moyen proxy inverse, voici une base de référence saine :
worker_processes auto;
worker_rlimit_nofile 65536;
events {
worker_connections 8192;
multi_accept off;
}
Pourquoi multi_accept off ici ? C'est la valeur par défaut conservatrice sur de nombreux systèmes. L'activer peut aider un travailleur à vider rapidement une file d'attente d'acceptation en attente, mais sous certains modèles de trafic, cela peut permettre à un travailleur de saisir un lot important tandis que d'autres restent inactifs. Si vous avez un trafic par à-coups et une raison testée de l'activer, faites-le. Si vous optimisez un serveur web polyvalent, gardez la base simple et mesurez d'abord.
Si le serveur gère de nombreuses connexions WebSocket, des événements envoyés par le serveur (Server-Sent Events) ou des flux API de longue durée, augmentez la limite de connexion de manière plus agressive et portez une attention particulière à la mémoire. Un serveur avec 20 000 clients WebSocket principalement inactifs a un profil différent d'un serveur effectuant 20 000 courtes requêtes de fichiers statiques.
Comment valider le changement
Avant de modifier la production, capturez une petite base de référence :
nginx -T | grep -E 'worker_processes|worker_connections|worker_rlimit_nofile'
ss -s
ulimit -n
Après le changement, vérifiez que Nginx l'a bien chargé :
sudo nginx -t
sudo systemctl reload nginx
ps -o pid,comm,nlwp,pcpu,pmem -C nginx
cat /proc/$(pgrep -n nginx)/limits | grep "open files"
Ensuite, observez le comportement pendant le trafic réel. Si tous les cœurs CPU sont occupés et que la latence augmente, Nginx effectue probablement un travail utile et atteint la capacité CPU. Si le CPU est faible mais que les connexions sont en file d'attente ou expirent, examinez les descripteurs de fichiers, la saturation en amont, la résolution DNS, les E/S disque ou les limites du pare-feu. Le réglage des travailleurs est un levier, pas toute l'histoire des performances.
Lire les chiffres dans leur contexte
Une erreur courante consiste à traiter les "connexions actives" comme la même chose que les "utilisateurs actifs". Ce n'est pas le cas. Un navigateur peut ouvrir plusieurs connexions pour des ressources. Un client API peut maintenir une connexion active entre les requêtes. Un client WebSocket peut maintenir une connexion pendant des heures tout en envoyant très peu de trafic. Lorsque vous dimensionnez worker_connections, pensez en termes de sockets simultanés, pas de personnes.
Pour un proxy inverse, n'oubliez pas non plus le côté amont. Si 4 000 clients attendent des réponses proxy, Nginx peut également détenir des milliers de sockets en amont. C'est pourquoi un serveur peut manquer de descripteurs de fichiers avant que le simple calcul côté client ne le suggère. Cela est particulièrement visible lorsque l'application en amont ralentit : les requêtes restent ouvertes plus longtemps, la concurrence augmente et Nginx commence à consommer plus de sockets même si le taux de requêtes entrantes n'a pas changé.
Les paramètres keep-alive influencent également cela. Des délais d'attente keep-alive longs réduisent le renouvellement des connexions, ce qui peut aider les sites très fréquentés, mais ils maintiennent également les sockets inactifs plus longtemps. Des délais d'attente keep-alive très courts libèrent les sockets plus rapidement mais peuvent augmenter les négociations TLS et la surcharge de configuration de connexion. Il n'y a pas de valeur parfaite ; utilisez la forme du trafic comme guide. Un site web public avec de nombreuses visites courtes peut nécessiter un équilibre différent d'une API interne avec un petit nombre de clients persistants.
Si vous optimisez à l'intérieur d'un conteneur, vérifiez les limites à l'intérieur du conteneur et au niveau de l'hôte ou de l'orchestrateur. Un pod Kubernetes, un conteneur Docker ou un service systemd peut avoir une limite nofile inférieure à celle du shell hôte que vous avez utilisé pour tester. Vérifiez toujours le processus Nginx en cours d'exécution, pas seulement votre session de connexion.
Résumé des meilleures pratiques
| Directive | Valeur recommandée | Justification |
|---|---|---|
worker_processes |
auto (ou nombre de cœurs) |
Garantit une utilisation optimale du CPU et minimise la surcharge due aux changements de contexte. |
worker_connections |
Commencez par quelques milliers ; augmentez en fonction de la concurrence mesurée | Fournit une marge de connexion sans masquer d'autres goulots d'étranglement. |
Limite OS (ulimit -n) |
Supérieure aux besoins de connexion par travailleur, avec une marge supplémentaire | Fournit des descripteurs de fichiers pour les sockets clients, les sockets amont, les journaux et les fichiers cache. |
multi_accept |
Testez avant d'activer | Peut aider lors des pics, mais n'est pas automatiquement meilleur pour chaque charge de travail. |
La meilleure configuration des travailleurs Nginx est généralement simple : worker_processes auto, une limite de connexion qui reflète la concurrence réelle, et des limites de descripteurs de fichiers suffisamment élevées pour la charge de travail. Réglez-la, vérifiez les limites actives des processus et continuez à surveiller le journal des erreurs. Si les symptômes pointent vers l'amont, corrigez l'amont au lieu de faire accepter à Nginx plus de travail que l'application ne peut en terminer.