Résoudre l’épuisement des ports éphémères dans NGINX et NGINX Plus

NGINX | 19 avril 2016

NGINX et NGINX Plus sont des équilibreurs de charge HTTP, TCP et UDP extrêmement puissants. Ils sont très efficaces pour relayer d’importants pics de requêtes et maintenir un grand nombre de connexions simultanées. Mais ces caractéristiques rendent NGINX et NGINX Plus particulièrement sujets à l’épuisement des ports éphémères – une situation dans laquelle aucune nouvelle connexion ne peut être créée, car le système d’exploitation a épuisé les numéros de port alloués à l’établissement de nouveaux sockets locaux. (L’épuisement des ports éphémères concerne les deux produits, mais, par souci de concision, nous ne mentionnerons plus que NGINX Plus dans la suite de cet article.)

Dans cet article, nous passons en revue les composants d’une connexion TCP et la manière dont leur contenu est déterminé avant l’établissement de la connexion. Nous expliquons ensuite comment déterminer si NGINX Plus est affecté par l’épuisement des ports éphémères. Enfin, nous présentons des stratégies permettant de remédier à ces limitations en ajustant à la fois le noyau Linux et les directives de NGINX Plus.

Bref aperçu des sockets réseau

Lorsqu’une connexion est établie via TCP, un socket est créé à la fois sur l’hôte local et sur l’hôte distant. Ces sockets sont ensuite connectés pour former une paire de sockets, décrite par un quadruplet unique composé de l’adresse IP et du port locaux, ainsi que de l’adresse IP et du port distants.

L’adresse IP distante et le port distant correspondent au côté serveur de la connexion et doivent être déterminés par le client avant même qu’il puisse établir la connexion. Dans la plupart des cas, le client choisit automatiquement l’adresse IP locale à utiliser pour la connexion, mais celle-ci est parfois choisie par le logiciel qui établit la connexion. Enfin, le port local est sélectionné aléatoirement dans une plage définie mise à disposition par le système d’exploitation. Le port n’est associé au client que pendant la durée de la connexion ; il est donc qualifié d’éphémère». Lorsque la connexion prend fin, le port éphémère peut être réutilisé.

Reconnaître l’épuisement des ports éphémères

Comme indiqué dans l’introduction, NGINX Plus est, par nature, exposé à l’épuisement des ports éphémères et aux problèmes qui en découlent. Lorsque NGINX Plus transmet une requête à un serveur en amont, il joue le rôle du client dans le processus de création de socket décrit ci-dessus. Par défaut, il associe automatiquement le socket de la requête transmise à une adresse IP locale et à un port éphémère disponible sur l’hôte où il s’exécute. Si le taux de connexion est élevé, au point que les sockets établis passent en état d’attente plus rapidement que les sockets ouverts existants ne sont fermés, les ports disponibles finissent par être épuisés et aucun nouveau socket ne peut être créé. Cela entraîne des erreurs provenant à la fois du système d’exploitation et de NGINX Plus. Voici un exemple de l’erreur générée dans le journal des erreurs de NGINX Plus.

2016/03/18 09:08:37 [crit] 1888#1888: *13 connect() to 10.2.2.77:8081 failed (99: Cannot assign requested address) while connecting to upstream, client: 10.2.2.42, server: , request: "GET / HTTP/1.1", upstream: "http://10.2.2.77:8081/", host: "10.2.2.77"

L’épuisement des ports entraîne également une hausse des erreurs 500 générées par NGINX Plus plutôt que par le serveur en amont. Voici un exemple d’entrée dans le journal d’accès de NGINX Plus.

10.2.2.42 - - [18/Mar/2016:09:14:20 -0700] "GET / HTTP/1.1" 500 192 "-" "curl/7.35.0"

Pour vérifier le nombre de sockets à l’état « TIME-WAIT » sur votre serveur NGINX Plus, exécutez la commande ss suivante dans le shell Linux. L’exemple montre que 143 sockets sont ouvertes avec l’état « TIME-WAIT ». Dans cet exemple, nous obtenons ce nombre à l’aide de la commande wc qui compte le nombre de lignes dans la sortie de la commande.

# ss -a | grep TIME-WAIT | wc -l143

Réglage du noyau pour augmenter le nombre de ports éphémères disponibles

Une façon de réduire l’épuisement des ports éphémères consiste à utiliser le paramètre du noyau Linux « net.ipv4.ip_local_port_range ». La plage par défaut s’étend généralement de 32768 à 61000.

Si vous constatez que vous êtes à court de ports éphémères, remplacer la plage par défaut par une plage allant de 1024 à 65000 constitue un moyen pratique de doubler le nombre de ports éphémères disponibles. Pour plus d’informations sur la modification des paramètres du noyau, consultez notre article de blog « Optimisation des performances de NGINX ».

Activation des connexions persistantes dans NGINX Plus

Une autre façon de réduire l’épuisement des ports éphémères consiste à activer les connexions persistantes entre NGINX Plus et les serveurs en amont. Dans l’implémentation la plus simple de HTTP, un client ouvre une nouvelle connexion, envoie la requête, lit la réponse, puis ferme la connexion afin de libérer les ressources associées.

Une connexion persistante reste ouverte après que le client a lu la réponse, afin de pouvoir être réutilisée pour les requêtes suivantes.

Utilisez la directive « keepalive » pour activer les connexions persistantes entre NGINX Plus et les serveurs en amont, en définissant le nombre maximal de connexions persistantes inactives aux serveurs en amont qui sont conservées dans le cache de chaque processus de travail. Lorsque ce nombre est dépassé, les connexions les moins récemment utilisées sont fermées. Sans connexions persistantes, vous augmentez la surcharge et utilisez moins efficacement les connexions et les ports éphémères.

L’exemple de configuration suivant indique à NGINX Plus de maintenir au moins 128 connexions persistantes avec les serveurs définis dans le bloc upstream appelé backend.

upstream backend {    server 10.0.0.100:1234;
    server 10.0.0.101:1234;
    keepalive 128;
}

Lorsque vous activez les connexions persistantes vers vos serveurs en amont, vous devez également utiliser la directive proxy_http_version pour indiquer à NGINX Plus d’utiliser la version 1.1 de HTTP, ainsi que la directive proxy_set_header pour supprimer tous les en-têtes nommés Connection. Ces deux directives peuvent être placées dans les blocs de configuration http, server ou location.

proxy_http_version 1.1; proxy_set_header Connection "";

Liaison dynamique des connexions à une liste définie d’adresses IP locales

L’optimisation du noyau et l’activation des connexions persistantes permettent de mieux contrôler la disponibilité et l’utilisation des ports éphémères. Toutefois, dans certaines situations, ces modifications ne suffisent pas à limiter leur utilisation excessive. Dans ce cas, nous pouvons recourir à certaines directives et à certains paramètres de NGINX Plus afin d’associer une partie de nos connexions à des adresses IP locales statiques. Cela multiplie de fait le nombre de ports éphémères disponibles par le nombre d’adresses IP définies dans la configuration. Pour ce faire, nous utilisons les directives proxy_bind et split_clients.

Dans l’exemple de configuration ci-dessous, la directive proxy_bind du bloc location définit l’adresse IP locale lors de chaque requête en fonction de la valeur de la variable $split_ip. Nous attribuons dynamiquement à cette variable la valeur générée par le bloc split_clients, qui utilise une fonction de hachage pour déterminer cette valeur.

Le premier paramètre de la directive split_clients est une chaîne de caractères ("$remote_addr$remote_port") qui est hachée à l’aide d’une fonction MurmurHash2 lors de chaque requête. Le second paramètre ($split_ip) est la variable que nous définissons dynamiquement en fonction du hachage du premier paramètre.

Les instructions entre accolades divisent la table de hachage en « compartiments », chacun contenant un certain pourcentage des hachages. Ici, nous divisons la table en 10 compartiments de même taille, mais nous pouvons en créer autant que nous le souhaitons, et ils ne doivent pas nécessairement tous avoir la même taille. (Le pourcentage du dernier compartiment est toujours représenté par un astérisque [*] plutôt que par un nombre précis, car le nombre de hachages peut ne pas être divisible de manière égale selon les pourcentages spécifiés.)

La plage des valeurs de hachage possibles s’étend de 0 à 4294967295. Dans notre cas, chaque compartiment contient donc environ 429496700 valeurs (10 % du total) : le premier compartiment contient les valeurs de 0 à 429496700, le deuxième celles de 429496701 à 858993400, et ainsi de suite. La variable $split_ip est définie sur l’adresse IP associée au compartiment contenant le hachage de la chaîne $remote_addr$remote_port. Prenons un exemple concret : la valeur de hachage 150000000 se trouve dans le quatrième compartiment. Dans ce cas, la variable $split_ip est donc dynamiquement définie sur 10.0.0.213.

http {    upstream backend {
        server 10.0.0.100:1234;
        server 10.0.0.101:1234;
 }

    server {
        # ...
        location / {
            # ...
            proxy_pass http://backend;
            proxy_bind $split_ip;
            proxy_set_header X-Forwarded-For $remote_addr;
        }
    }

    split_clients "$remote_addr$remote_port" $split_ip { 10% 10.0.0.210; 10% 10.0.0.211; 10% 10.0.0.212; 10% 10.0.0.213; 10% 10.0.0.214; 10% 10.0.0.215; 10% 10.0.0.216; 10% 10.0.0.217; 10% 10.0.0.218; * 10.0.0.219; }
}

Conclusion

L’ajustement du paramètre du noyau Linux relatif au nombre de ports éphémères permet d’optimiser leur disponibilité et leur utilisation. L’activation des connexions persistantes entre NGINX Plus et vos serveurs en amont permet d’utiliser plus efficacement les ports éphémères. Enfin, l’utilisation des directives split_clients et proxy_bind dans votre configuration NGINX Plus vous permet d’associer dynamiquement les connexions sortantes à une liste définie d’adresses IP locales, ce qui augmente considérablement le nombre de ports éphémères disponibles pour NGINX Plus.

Pour essayer NGINX Plus, commencez votre essai gratuit de 30 jours dès aujourd’hui ou contactez-nous pour discuter de vos cas d’utilisation.


Partager

À propos de l’auteur

Kevin Jones
Kevin JonesChef de produit senior | F5 NGINX

Autres articles de Kevin Jones

Articles de blog associés

Tendances actuelles des technologies cloud natives, de l’ingénierie de plateforme et de l’IA
NGINX | 13/10/2025

Tendances actuelles des technologies cloud natives, de l’ingénierie de plateforme et de l’IA

Découvrez les principaux enseignements tirés des réponses à l’enquête annuelle F5 NGINX sur les dernières tendances en matière de technologies cloud natives, de sécurité, d’ingénierie de plateforme et d’IA.

Quels contrôleurs Ingress NGINX sont affectés par les vulnérabilités CVE-2022-4886, CVE-2023-5043 et CVE-2023-5044 ?
NGINX | 03/11/2023

Quels contrôleurs Ingress NGINX sont affectés par les vulnérabilités CVE-2022-4886, CVE-2023-5043 et CVE-2023-5044 ?

Lorsque de nouvelles CVE sont signalées, il est facile de ne plus savoir si elles concernent un outil de contrôleur Ingress NGINX particulier, car il existe plusieurs projets. Cet article présente les CVE et explique comment distinguer les différents projets de contrôleurs Ingress afin de dissiper toute confusion.

Votre API est-elle en temps réel ? Testez sa latence avec l’outil rtapi de NGINX
NGINX | 11/03/2020

Votre API est-elle en temps réel ? Testez sa latence avec l’outil rtapi de NGINX

Votre API répond-elle aux requêtes en moins de 30 ms ? Si ce n’est pas le cas, il ne s’agit pas d’une API en temps réel offrant la faible latence exigée par la grande majorité des organisations. Mesurez la latence de votre API avec l’outil rtapi de NGINX et découvrez comment NGINX peut l’aider à offrir une réactivité en temps réel.

Un testeur d’expressions régulières pour NGINX et NGINX Plus
NGINX | 11/06/2019

Un testeur d’expressions régulières pour NGINX et NGINX Plus

Le testeur d’expressions régulières (regex) pour NGINX et NGINX Plus vous évite de tâtonner en vous indiquant si une expression régulière utilisée dans un bloc location ou map correspond aux valeurs comme prévu. Il génère la configuration appropriée et affiche les valeurs des groupes de capture.

Caches partagés avec les clusters de cache NGINX Plus, partie 1
NGINX | 24/01/2017

Caches partagés avec les clusters de cache NGINX Plus, partie 1

Optimisez la capacité de votre cache web en le répartissant entre plusieurs serveurs de cache web NGINX ou NGINX Plus. Découvrez comment procéder dans cet article.

Introduction aux microservices
NGINX | 19/05/2015

Introduction aux microservices

Les microservices suscitent actuellement beaucoup d’intérêt. Cet article de blog est le premier d’une série de sept consacrée à la conception, au développement et au déploiement de microservices.