web-dev-qa-db-fra.com

Pourquoi les connexions à l'état FIN_WAIT2 ne sont-elles pas fermées par le noyau Linux?

J'ai un problème dans un processus de longue durée appelé kube-proxy faisant partie de Kubernetes .

Le problème est que de temps en temps une connexion est laissée dans l'état FIN_WAIT2.

$ Sudo netstat -tpn | grep FIN_WAIT2
tcp6       0      0 10.244.0.1:33132        10.244.0.35:48936       FIN_WAIT2   14125/kube-proxy
tcp6       0      0 10.244.0.1:48340        10.244.0.35:56339       FIN_WAIT2   14125/kube-proxy
tcp6       0      0 10.244.0.1:52619        10.244.0.35:57859       FIN_WAIT2   14125/kube-proxy
tcp6       0      0 10.244.0.1:33132        10.244.0.50:36466       FIN_WAIT2   14125/kube-proxy

Ces connexions s'empilent au fil du temps, ce qui rend le processus inapproprié. J'ai déjà signalé un problème à Kubernetes bug-tracker mais j'aimerais comprendre pourquoi de telles connexions ne sont pas fermées par le noyau Linux.

Selon son documentation (recherche de tcp_fin_timeout) la connexion dans l'état FIN_WAIT2 devrait être fermée par le noyau après X secondes, où X peut être lu depuis/proc. Sur ma machine, il est réglé sur 60:

$ cat /proc/sys/net/ipv4/tcp_fin_timeout
60

donc si je comprends bien, ces connexions doivent être fermées de 60 secondes. Mais ce n'est pas le cas, ils sont laissés dans cet état pendant des heures.

Bien que je comprenne également que les connexions FIN_WAIT2 sont assez inhabituelles (cela signifie que l'hôte attend un ACK de l'extrémité distante de la connexion qui pourrait déjà avoir disparu), je ne comprends pas pourquoi ces connexions ne sont pas "fermées" par le système .

Y a-t-il quelque chose que je puisse faire à ce sujet?

Notez que le redémarrage du processus associé est un dernier recours.

11
Adam Romanek

Le délai d'expiration du noyau s'applique uniquement si la connexion est orpheline. Si la connexion est toujours attachée à un socket, le programme propriétaire de ce socket est responsable de la temporisation de l'arrêt de la connexion. Il a probablement appelé shutdown et attend que la connexion s'arrête proprement. L'application peut attendre aussi longtemps qu'elle le souhaite pour que l'arrêt se termine.

Le flux d'arrêt propre typique se présente comme suit:

  1. L'application décide de fermer la connexion et ferme le côté écriture de la connexion.

  2. L'application attend que l'autre côté ferme sa moitié de connexion.

  3. L'application détecte l'arrêt de la connexion de l'autre côté et ferme son socket.

L'application peut attendre à l'étape 2 aussi longtemps qu'elle le souhaite.

Il semble que l'application ait besoin d'un délai d'attente. Une fois qu'il décide de fermer la connexion, il devrait renoncer à attendre que l'autre côté fasse un arrêt net après un certain temps.

14
David Schwartz

Si le socket est shutdown (), mais pas encore close (), le socket restera dans l'état FIN_WAIT2. Et puisque l'application possède toujours le descripteur de fichier, le noyau ne prendrait pas la peine de nettoyer.

2
L. Yan