为什么 FIN_WAIT2 状态下的连接不会被 Linux 内核关闭?

为什么 FIN_WAIT2 状态下的连接不会被 Linux 内核关闭?

我在一个名为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并正在等待连接完全关闭。应用程序可以等待关闭完成,时间长短由其决定。

典型的干净关机流程如下:

  1. 应用程序决定关闭连接,并关闭连接的写入端。

  2. 应用程序等待另一端关闭其一半的连接。

  3. 应用程序检测到另一端的连接关闭并关闭其套接字。

应用程序可以在第 2 步等待任意长的时间。

听起来应用程序需要超时。一旦它决定关闭连接,它应该在一段合理的时间后放弃等待另一端完全关闭。

答案2

如果套接字已关闭(但尚未关闭),则套接字将保持 FIN_WAIT2 状态。而且由于应用程序仍然拥有文件描述符,因此内核不会费心进行清理。

相关内容