Ich habe ein Problem in einem langlebigen Prozess namens kube-proxy , der Teil von Kubernetes ist .
Das Problem ist, dass von Zeit zu Zeit eine Verbindung im Status FIN_WAIT2 verbleibt.
$ 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
Diese Verbindungen stapeln sich im Laufe der Zeit, wodurch sich der Prozess schlecht verhält. Ich habe Kubernetes Bug-Tracker bereits ein Problem gemeldet , möchte aber verstehen, warum solche Verbindungen vom Linux-Kernel nicht geschlossen werden.
Gemäß seiner Dokumentation (Suche nach tcp_fin_timeout) sollte die Verbindung im Status FIN_WAIT2 nach X Sekunden vom Kernel geschlossen werden, wobei X aus / proc gelesen werden kann. Auf meinem Computer ist es auf 60 eingestellt:
$ cat /proc/sys/net/ipv4/tcp_fin_timeout
60
Wenn ich es richtig verstehe, sollten solche Verbindungen um 60 Sekunden geschlossen sein. Dies ist jedoch nicht der Fall, sie bleiben stundenlang in einem solchen Zustand.
Obwohl ich auch verstehe, dass FIN_WAIT2-Verbindungen ziemlich ungewöhnlich sind (dies bedeutet, dass der Host auf eine Bestätigung vom Remote-Ende der Verbindung wartet, die möglicherweise bereits unterbrochen ist), verstehe ich nicht, warum diese Verbindungen vom System nicht "geschlossen" werden .
Kann ich etwas dagegen tun?
Beachten Sie, dass der Neustart des zugehörigen Prozesses ein letzter Ausweg ist.
quelle
Antworten:
Das Kernel-Timeout gilt nur, wenn die Verbindung verwaist ist. Wenn die Verbindung weiterhin an einen Socket angeschlossen ist, ist das Programm, dem dieser Socket gehört, dafür verantwortlich, das Herunterfahren der Verbindung zu beenden. Wahrscheinlich hat es angerufen
shutdown
und wartet darauf, dass die Verbindung sauber heruntergefahren wird. Die Anwendung kann so lange warten, bis das Herunterfahren abgeschlossen ist.Der typische saubere Abschaltfluss sieht folgendermaßen aus:
Die Anwendung beschließt, die Verbindung zu beenden und die Schreibseite der Verbindung zu beenden.
Die Anwendung wartet darauf, dass die andere Seite die Hälfte der Verbindung beendet.
Die Anwendung erkennt das Herunterfahren der Verbindung durch die andere Seite und schließt den Socket.
Die Anwendung kann in Schritt 2 so lange warten, wie sie möchte.
Es hört sich so an, als ob die Anwendung eine Zeitüberschreitung benötigt. Sobald es sich entscheidet, die Verbindung zu beenden, sollte es aufhören, darauf zu warten, dass die andere Seite nach einer angemessenen Zeitspanne ein sauberes Herunterfahren durchführt.
quelle
Wenn der Socket heruntergefahren (), aber noch nicht geschlossen () ist, bleibt der Socket im Status FIN_WAIT2. Und da die Anwendung immer noch den Dateideskriptor besitzt, würde sich der Kernel nicht darum kümmern, aufzuräumen.
quelle