NGINX et NGINX Plus sont des équilibreurs de charge HTTP , TCP et UDP extrêmement puissants. Ils sont très efficaces pour traiter de grandes quantités 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 éphémère des ports – une condition dans laquelle de nouvelles connexions ne peuvent pas être créées parce que le système d’exploitation n’a plus de numéros de ports alloués pour établir de nouveaux sockets locaux. (L'épuisement éphémère des ports s'applique aux deux produits, mais par souci de concision, nous nous référerons uniquement à NGINX Plus pour le reste de ce blog.)
Dans ce blog, nous examinons les composants d’une connexion TCP et la manière dont son contenu est déterminé avant l’établissement d’une connexion. Nous montrons ensuite comment déterminer quand NGINX Plus est affecté par l’épuisement éphémère des ports. Enfin, nous discutons des stratégies permettant de lutter contre ces limitations en utilisant à la fois des ajustements du noyau Linux et des directives NGINX Plus.
Lorsqu'une connexion est établie via TCP, un socket est créé sur l'hôte local et sur l'hôte distant. Ces sockets sont ensuite connectés pour créer une paire de sockets, qui est décrite par un 4-tuple unique composé de l'adresse IP et du port locaux ainsi que de l'adresse IP et du port distants.
L'adresse IP et le port distants appartiennent au côté serveur de la connexion et doivent être déterminés par le client avant même de pouvoir initier la connexion. Dans la plupart des cas, le client choisit automatiquement l'adresse IP locale à utiliser pour la connexion, mais parfois, elle est choisie par le logiciel établissant 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 est associé au client uniquement pendant la durée de la connexion et est donc qualifié d' éphémère . Lorsque la connexion est terminée, le port éphémère est disponible pour être réutilisé.
Comme mentionné dans l’introduction, NGINX Plus est par nature sujet à l’épuisement éphémère des ports et aux problèmes que cela entraîne. Lorsque NGINX Plus transmet une requête à un serveur en amont, il s'agit du client dans le processus de création de socket décrit ci-dessus, et son comportement par défaut consiste à lier automatiquement le socket de la requête proxy à une adresse IP locale et à un port éphémère disponible sur l'hôte sur lequel il s'exécute. Si le taux de connexion est élevé, de sorte que les sockets en cours d'établissement sont déplacés vers un état d'attente plus rapidement que les sockets ouverts existants ne sont fermés, alors les ports disponibles finissent par être épuisés et de nouveaux sockets ne peuvent pas être créés. Cela entraîne des erreurs à la fois du système d’exploitation et de NGINX Plus. Voici un exemple de l’erreur résultante dans le journal des erreurs NGINX Plus.
18/03/2016 09:08:37 [crit] 1888#1888 : *13 connexion() à 10.2.2.77:8081 a échoué (99 : Impossible d'attribuer l'adresse demandée ) lors de la connexion au client en amont : 10.2.2.42, serveur : , requête : "GET / HTTP/1.1", en amont : "http://10.2.2.77:8081/", hôte : "10.2.2.77"
L'épuisement des ports provoque également une augmentation500
les erreurs proviennent de NGINX Plus plutôt que du serveur en amont. Voici un exemple d'entrée dans le journal d'accès 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 dans l'état TIME-WAIT
sur votre serveur NGINX Plus, exécutez la commande ss
suivante dans le shell Linux. L'exemple montre qu'il y a 143 sockets ouverts avec le statut TIME-WAIT
. Dans l'exemple, nous obtenons le nombre en utilisant la commande wc
pour répertorier le nombre de lignes dans la sortie de la commande.
# ss -a | grep TEMPS-ATTENTE | wc -l143
Une façon de réduire l’épuisement des ports éphémères est d’utiliser le paramètre net.ipv4.ip_local_port_range
du noyau Linux. La plage par défaut est généralement comprise entre 32 768 et 61 000.
Si vous remarquez que vous manquez de ports éphémères, changer la plage par défaut de 1024 à 65000 est un moyen pratique de doubler le nombre de ports éphémères disponibles à l'utilisation. Pour plus d’informations sur la modification des paramètres du noyau, consultez notre article de blog Tuning NGINX for Performance .
Une autre façon de réduire l’épuisement des ports éphémères est d’activer les connexions keepalive entre NGINX Plus et les serveurs en amont. Dans l'implémentation la plus simple de HTTP, un client ouvre une nouvelle connexion, écrit la requête, lit la réponse, puis ferme la connexion pour libérer les ressources associées.
Une connexion keepalive est maintenue ouverte après que le client a lu la réponse, afin qu'elle puisse être réutilisée pour les demandes ultérieures.
Utilisez la directive keepalive
pour activer les connexions keepalive de NGINX Plus aux serveurs en amont, en définissant le nombre maximal de connexions keepalive 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 keepalives, vous ajoutez plus de frais généraux et êtes inefficace avec les connexions et les ports éphémères.
L'exemple de configuration suivant indique à NGINX Plus de maintenir au moins 128 connexions keepalive aux serveurs définis dans le bloc en amont
appelé backend .
backend en amont { serveur 10.0.0.100:1234;
serveur 10.0.0.101:1234;
keepalive 128;
}
Lorsque vous activez les connexions keepalive vers vos serveurs en amont, vous devez également utiliser la directive proxy_http_version
pour indiquer à NGINX Plus d'utiliser la version HTTP 1.1 et la directive proxy_set_header
pour supprimer tous les en-têtes nommés Connection
. Les deux directives peuvent être placées dans les blocs de configuration http
, server
ou location
.
proxy_http_version 1.1; proxy_set_header Connexion "";
L’optimisation du noyau et l’activation des connexions keepalive offrent un meilleur contrôle de la disponibilité et de l’utilisation des ports éphémères, mais il existe certaines situations où ces changements ne suffisent pas à lutter contre l’utilisation excessive des ports éphémères. Dans ce cas, nous pouvons utiliser certaines directives et paramètres NGINX Plus qui nous permettent de lier un pourcentage de nos connexions à des adresses IP locales statiques. Cela multiplie efficacement 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
dans le bloc d'emplacement
définit l'adresse IP locale lors de chaque requête en fonction de la valeur de la variable $split_ip
. Nous définissons cette variable de manière dynamique sur 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 ( "$remote_addr$remote_port"
) qui est hachée à l'aide d'une fonction MurmurHash2 lors de chaque requête. Le deuxième paramètre ( $split_ip
) est la variable que nous définissons dynamiquement en fonction du hachage du premier paramètre.
Les instructions à l’intérieur des accolades divisent la table de hachage en « compartiments », chacun contenant un pourcentage des hachages. Ici, nous divisons le tableau en 10 compartiments de la même taille, mais nous pouvons créer n'importe quel nombre de compartiments et ils ne doivent pas tous avoir la même taille. (Le pourcentage du dernier bucket est toujours représenté par l'astérisque [ * ] plutôt que par un nombre spécifique, car le nombre de hachages peut ne pas être divisible de manière égale dans les pourcentages spécifiés.)
La plage des valeurs de hachage possibles est comprise entre 0 et 4294967295, donc dans notre cas, chaque bucket contient environ 429496700 valeurs (10 % du total) : le premier bucket contient les valeurs de 0 à 429496700, le deuxième bucket de 429496701 à 858993400, et ainsi de suite. La variable $split_ip
est définie sur l'adresse IP associée au bucket contenant le hachage de la chaîne $remote_addr$remote_port
. À titre d’exemple spécifique, la valeur de hachage 150000000 se trouve dans le quatrième compartiment, donc la variable $split_ip
est définie dynamiquement sur 10.0.0.213 dans ce cas.
http { backend en amont { serveur 10.0.0.100:1234 ; serveur 10.0.0.101:1234 ; } serveur { # ... emplacement / { # ... 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 ; } }
Le réglage du nombre de ports éphémères dans le noyau Linux offre une disponibilité et une utilisation plus efficaces. L'activation des connexions keepalive de NGINX Plus vers vos serveurs en amont rend leur consommation de ports éphémères plus efficace. Enfin, l’utilisation des directives split_clients
et proxy_bind
dans votre configuration NGINX Plus vous permet de lier dynamiquement les connexions sortantes à une liste définie d’adresses IP locales, augmentant considérablement le nombre de ports éphémères disponibles pour NGINX Plus.
Pour essayer NGINX Plus, démarrez votre essai gratuit de 30 jours dès aujourd'hui ou contactez-nous pour discuter de vos cas d'utilisation.
« Cet article de blog peut faire référence à des produits qui ne sont plus disponibles et/ou qui ne sont plus pris en charge. Pour obtenir les informations les plus récentes sur les produits et solutions F5 NGINX disponibles, explorez notre famille de produits NGINX . NGINX fait désormais partie de F5. Tous les liens NGINX.com précédents redirigeront vers un contenu NGINX similaire sur F5.com."