14

我需要在任何连接上启用 TCP keepalive,现在我正在努力处理我们测试用例的结果。我认为这是因为我不太了解何时发送第一个 keepalive 探测。tcp_keepalive_time我在 Linux 上的文档中阅读了以下内容:

发送的最后一个数据包(简单的 ACK 不被视为数据)和第一个 keepalive 探测之间的间隔;在连接被标记为需要保持连接后,此计数器不再使用

其他一些消息来源指出这是连接空闲的时间,但他们没有进一步定义这意味着什么。我还研究了史蒂文斯以找到一个更正式的定义,因为我想知道在考虑重传时“发送的最后一个数据包”实际上意味着什么。

在我的测试用例中,我有一个连接,其中数据仅以相当高的速率从服务器发送到客户端。为了测试 keepalive,我们拔掉了客户端 NIC 上的电缆。我现在可以看到网络堆栈尝试发送数据并进入重传状态,但没有发送保持活动探测。在重传期间不发送保持活动探测是否正确?

4

1 回答 1

22

我有一个连接,其中数据仅以相当高的速率从服务器发送到客户端。

然后你永远不会看到keepalives。当“线路保持沉默”时,会发送 Keepalive。RFC1122对keepalives 有一些解释。

当连接处于空闲状态时, “保持活动”机制会定期探测连接的另一端,即使没有要发送的数据也是如此

回到你的问题:

其他一些消息来源指出这是连接空闲的时间,但他们没有进一步定义这意味着什么。

这是 TCP 在戳对等方“天哪!还活着?”之前将等待多长时间。

$ cat /proc/sys/net/ipv4/tcp_keepalive_time
7200

换句话说,您一直在使用 TCP 连接,而且非常棒。但是,在过去的 2 个小时里,没有任何东西可以发送。假设连接仍然存在是否合理?假设中间的所有中间盒仍然具有您的连接状态是否合理?意见各不相同,keepalive 不是 RFC793 的一部分。

TCP 规范不包含保持活动的机制,它可能:(1)在短暂的 Internet 故障期间导致完全良好的连接中断;(2)消耗不必要的带宽(“如果没有人在使用连接,谁在乎它是否仍然好?”)


为了测试 keepalive,我们拔掉了客户端 NIC 上的电缆。

这不是测试保活。这是测试您的 TCP 重传策略,即 TCP 尝试传递您的消息的次数和频率。在 Linux 机器上,这(可能)最终会测试net.ipv4.tcp_retries2

在杀死活动 TCP 连接之前重试多少次。RFC 1122 说限制应该超过 100 秒。这个数字太小了。默认值 15 对应于 13-30 分钟,具体取决于 RTO。

但是RFC5482 - TCP User Timeout Option提供了更多影响它的方法。

TCP 用户超时控制在强制关闭连接之前传输的数据可能保持未确认的时间。

回到问题:

在重传期间不发送保持活动探针是否正确

这是有道理的:TCP 已经在尝试从其他对等方获取响应,空的 keepalive 将是多余的。


影响 keepalive的特定于 Linux (2.4+) 的选项

  • TCP_KEEPCNTTCP 在断开连接之前应发送的最大保活探测数。

  • TCP_KEEPIDLESO_KEEPALIVE如果已在此套接字上设置了套接字选项,则在 TCP 开始发送 keepalive 探测之前连接需要保持空闲的时间(以秒为单位)

  • TCP_KEEPINTVL各个保活探测之​​间的时间(以秒为单位)

影响 TCP 用户超时的 Linux 特定 (2.6.37+)选项

TCP_USER_TIMEOUT在 TCP 强制关闭连接之前,传输数据可能保持未确认的最长时间(以毫秒为单位)。

因此,例如,您的应用程序可以使用此选项来确定在没有连接时连接可以存活多长时间(类似于您的 NIC 拔出示例)。例如,如果您有理由相信客户端会回来(也许他们关上了笔记本电脑的盖子?无线访问不稳定?)您可以指定 12 小时的超时时间,当他们回来时,连接仍然有效。

于 2016-06-20T09:04:01.543 回答