我在一个名为kube-proxy成为其中的一部分Kubernetes。
问题是,有时连接会处于 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
这些连接随着时间的推移不断累积,导致流程出现问题。我已经报告问题到 Kubernetes 错误跟踪器,但我想了解为什么 Linux 内核不关闭此类连接。
根据其文档(搜索 tcp_fin_timeout)FIN_WAIT2 状态的连接应在 X 秒后由内核关闭,其中 X 可从 /proc 读取。在我的计算机上,它设置为 60:
$ cat /proc/sys/net/ipv4/tcp_fin_timeout
60
因此,如果我理解正确的话,此类连接应在 60 秒内关闭。但事实并非如此,它们处于这种状态长达数小时。
虽然我也知道 FIN_WAIT2 连接非常不寻常(这意味着主机正在等待连接远端的某个 ACK,而该 ACK 可能已经消失)但我不明白为什么这些连接没有被系统“关闭”。
我能做些什么吗?
请注意,重新启动相关进程是最后手段。
答案1
内核超时仅适用于连接处于孤立状态的情况。如果连接仍连接到套接字,则拥有该套接字的程序负责超时关闭连接。它可能已调用shutdown
并正在等待连接完全关闭。应用程序可以等待关闭完成,时间长短由其决定。
典型的干净关机流程如下:
应用程序决定关闭连接,并关闭连接的写入端。
应用程序等待另一端关闭其一半的连接。
应用程序检测到另一端的连接关闭并关闭其套接字。
应用程序可以在第 2 步等待任意长的时间。
听起来应用程序需要超时。一旦它决定关闭连接,它应该在一段合理的时间后放弃等待另一端完全关闭。
答案2
如果套接字已关闭(但尚未关闭),则套接字将保持 FIN_WAIT2 状态。而且由于应用程序仍然拥有文件描述符,因此内核不会费心进行清理。