为什么Linux内核没有关闭FIN_WAIT2状态的连接?


11

我有一个叫长寿命过程中的问题KUBE-代理的存在部分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秒钟后由内核关闭,其中可以从/ proc读取X。在我的机器上,它设置为60:

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

因此,如果我理解正确,则此类连接应在60秒内关闭。但是事实并非如此,它们会处于这种状态数小时。

虽然我也知道FIN_WAIT2连接是非常不寻常的(这意味着主机正在等待连接的远程端可能已经消失的ACK),但我不明白为什么这些连接不会被系统“关闭” 。

有什么我可以做的吗?

请注意,重启相关过程是万不得已的方法。


1
顺便说一句,在FIN-WAIT2中,连接等待ACK(已确认发送的FIN,这就是为什么我们不在FIN-WAIT1中的原因)。相反,另一端仍然可以选择发送无限量的数据。
哈根·冯·埃岑2015年

Answers:


14

内核超时仅在孤立连接时适用。如果连接仍连接到套接字,则拥有该套接字的程序负责超时关闭连接。它可能已调用shutdown并正在等待连接完全关闭。该应用程序可以等待关闭的时间,只要它喜欢即可。

典型的干净关闭流程如下所示:

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

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

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

该应用程序可以根据需要在步骤2中等待。

听起来应用程序需要超时。一旦决定关闭连接,它就应该放弃等待合理的时间后等待另一端进行干净的关闭。


我将与Kubernetes开发人员一起检查此信息,以查看是否实现了这种超​​时。验证后,我会接受答案。不过,感谢您的快速回复。
亚当·罗曼尼克

我想更详细地了解您的答案。您能解释一下什么是孤立连接吗?
亚当·罗曼尼克

1
@AdamRomanek孤立连接是一个没有关联套接字的连接,即只能由内核本身访问的套接字,并且没有进程可以对其执行操作。
David Schwartz

这将有助于...” blog.cloudflare.com/...
约翰·格林

2

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


接受的答案中已经提到了这一点。
RalfFriedl '19

我专门添加了未调用close()的内容。
L. Yan,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.