Supposons qu'il existe un client qui établit beaucoup de connexions éphémères à un serveur.
Si le client ferme la connexion, il y aura beaucoup de ports dans l'état TIME_WAIT
du côté client. Comme le client manque de ports locaux, il devient impossible de faire une nouvelle tentative de connexion rapidement.
Si le serveur ferme la connexion, je verrai beaucoup de TIME_WAIT
s du côté du serveur. Cependant, cela fait-il du mal? Le client (ou d'autres clients) peut continuer à faire des tentatives de connexion puisqu'il ne manque jamais de ports locaux et que le nombre d'états TIME_WAIT
augmentera côté serveur. Qu'est-ce qui se passe finalement? Quelque chose de mauvais arrive? (ralentissement, crash, connexions perdues, etc.)
Veuillez noter que ma question n'est pas "Quel est l'objectif de TIME_WAIT
?" mais "que se passe-t-il s'il y a autant d'états TIME_WAIT
sur le serveur?" Je sais déjà ce qui se passe lorsqu'une connexion est fermée en TCP/IP et pourquoi l'état TIME_WAIT
est requis. Je n'essaie pas de le dépanner mais je veux juste savoir quel est le problème potentiel avec cela.
Pour le dire simplement, supposons que netstat -nat | grep :8080 | grep TIME_WAIT | wc -l
imprime 100000
. Ce qui se passerait? Est-ce que la pile réseau O/S ralentit? Erreur "Trop de fichiers ouverts"? Ou simplement rien d'inquiétant?
Chaque socket dans TIME_WAIT
consomme de la mémoire dans le noyau, généralement un peu moins qu'un socket ESTABLISHED
tout en restant significatif. Un nombre suffisamment important pourrait épuiser la mémoire du noyau ou au moins dégrader les performances car cette mémoire pourrait être utilisée à d'autres fins. Les sockets TIME_WAIT
ne contiennent pas de descripteurs de fichiers ouverts (en supposant qu'ils aient été fermés correctement), vous ne devriez donc pas avoir à vous soucier d'une erreur "trop de fichiers ouverts".
Le socket lie également cette adresse IP et ce port src
/dst
de sorte qu'il ne puisse pas être réutilisé pendant la durée de l'intervalle TIME_WAIT
. (C’est le but recherché de l’état TIME_WAIT
.) La connexion du port n’est généralement pas un problème, sauf si vous devez vous reconnecter avec la même paire de ports. Le plus souvent, un côté utilise un port éphémère, un seul côté étant ancré à un port bien connu. Cependant, un très grand nombre de sockets TIME_WAIT
peut épuiser l’espace de port éphémère si vous vous connectez de manière répétée et fréquente entre les deux mêmes adresses IP. Notez que cela n'affecte que cette paire d'adresses IP particulière et n'affectera pas l'établissement de connexions avec d'autres hôtes.
Conclusions jusqu'ici:
Même si le serveur a fermé le socket à l'aide d'un appel système, son descripteur de fichier ne sera pas publié s'il passe à l'état TIME_WAIT. Le descripteur de fichier sera publié ultérieurement lorsque l'état TIME_WAIT aura disparu (c'est-à-dire après 2 * MSL secondes). Par conséquent, trop de TIME_WAIT entraînera probablement une erreur «trop de fichiers ouverts» dans le processus du serveur.
Je pense que la pile TCP/IP O/S a été mise en œuvre avec la structure de données appropriée (par exemple, une table de hachage). Le nombre total de TIME_WAIT ne doit donc pas affecter les performances de la pile TCP/IP O/S. Seul le processus (serveur) qui possède les sockets à l'état TIME_WAIT en souffrira.
Chaque connexion est identifiée par un tuple (IP du serveur, port du serveur, IP du client, port du client). De manière cruciale, les connexions TIME_WAIT
(qu’elles soient côté serveur ou côté client) occupent chacune l’un de ces n-uplets.
Avec le TIME_WAIT
s du côté client, il est facile de comprendre pourquoi vous ne pouvez plus établir de connexions - vous n’avez plus de ports locaux. Cependant, le même problème s’applique côté serveur - une fois qu’il dispose de connexions de 64 Ko dans TIME_WAIT
état pour un seul client , il ne peut plus accepter de connexions de ce client , car il ne dispose pas dire la différence entre l'ancienne connexion et la nouvelle connexion - les deux connexions sont identifiées par le même Tuple. Le serveur doit simplement renvoyer RST
s aux nouvelles tentatives de connexion de ce client dans ce cas.
Si vous avez beaucoup de connexions depuis plusieurs adresses IP clientes vers les adresses IP du serveur, vous risquez de rencontrer des limitations du tableau de suivi des connexions.
Vérifier:
sysctl net.ipv4.netfilter.ip_conntrack_count
sysctl net.ipv4.netfilter.ip_conntrack_max
Sur tous les tuples src ip/port et dest ip/port, vous ne pouvez avoir que net.ipv4.netfilter.ip_conntrack_max dans la table de suivi. Si cette limite est atteinte, vous verrez un message dans vos journaux "nf_conntrack: table full, droping packet". et le serveur n'acceptera pas de nouvelles connexions entrantes tant qu'il n'y aura plus d'espace disponible dans la table de suivi.
Cette limitation peut vous toucher bien avant que les ports éphémères ne soient épuisés.
Dans mon scénario, j’ai exécuté un script qui planifie les fichiers de façon répétée, mon produit effectue des calculs et envoie une réponse au client, c’est-à-dire que le client effectue un appel http répétitif pour obtenir la réponse de chaque fichier. dans l'état time_wait et une exception est levée dans le client, ce qui ouvre une connexion http, c'est-à-dire
Error : [Errno 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
Le résultat a été que mon application a été pendue. Je ne sais pas si les threads sont partis en attente ou ce qui est arrivé, mais je dois supprimer tous les processus ou redémarrer mon application pour la faire fonctionner à nouveau.
J'ai essayé de réduire le temps d'attente à 30 secondes car il s'agit de 240 secondes par défaut, mais cela n'a pas fonctionné.
Donc, fondamentalement, l’impact global était critique car il a rendu mon application non réactive