Linux 内置了对 keepalive 的支持。你需要启用 TCP/IP 网络才能使用它。你还需要procfs支持 和sysctl支持,以便能够在运行时配置内核参数。
涉及 keepalive 的过程使用三个用户驱动的变量
上次发送数据包(简单的 ACK 不被视为数据)和第一次 keepalive 探测之间的时间间隔;在连接被标记为需要 keepalive 后,此计数器不再使用
后续 keepalive 探测之间的时间间隔,无论连接在此期间交换了什么
在认为连接已断开并通知应用层之前,要发送的未被确认的探测数量
请记住,即使在内核中配置了 keepalive 支持,它也不是 Linux 中的默认行为。程序必须使用setsockopt接口为其套接字请求 keepalive 控制。实现 keepalive 的程序相对较少,但是您可以按照本文档后面解释的说明轻松地为大多数程序添加 keepalive 支持。
有两种方法可以通过用户空间命令在内核内部配置 keepalive 参数
procfs接口
sysctl接口
我们主要讨论如何在 procfs 接口上完成此操作,因为它是最常用、推荐且最容易理解的。sysctl 接口,特别是关于 sysctl(2) 系统调用而不是 sysctl(8) 工具,仅在此处用于提供背景知识。
此接口需要sysctl和procfs构建到内核中,并且procfs挂载在文件系统中的某个位置(通常在/proc,如下面的示例所示)。您可以通过 "cat"/proc/sys/net/ipv4/目录中的文件来读取实际参数的值
# cat /proc/sys/net/ipv4/tcp_keepalive_time 7200 # cat /proc/sys/net/ipv4/tcp_keepalive_intvl 75 # cat /proc/sys/net/ipv4/tcp_keepalive_probes 9 |
前两个参数以秒为单位表示,最后一个是纯数字。这意味着 keepalive 例程在发送第一个 keepalive 探测之前等待两个小时(7200 秒),然后每 75 秒重新发送一次。如果连续九次未收到 ACK 响应,则连接被标记为断开。
修改此值非常简单:您需要将新值写入文件。假设您决定配置主机,以便 keepalive 在通道不活动十分钟后开始,然后以一分钟的间隔发送探测。由于我们的网络主干的高度不稳定性和间隔的低值,假设您还想将探测次数增加到 20。
以下是我们如何更改设置的方法
# echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time # echo 60 > /proc/sys/net/ipv4/tcp_keepalive_intvl # echo 20 > /proc/sys/net/ipv4/tcp_keepalive_probes |
为确保一切成功,请重新检查文件并确认这些新值显示在旧值的位置。
请记住procfs处理特殊文件,您不能对它们执行任何类型的操作,因为它们只是内核空间中的一个接口,而不是真实文件,因此请在使用脚本之前进行尝试,并尝试使用简单的访问方法,如前面示例中所示。
您可以通过 sysctl(8) 工具访问该接口,指定您要读取或写入的内容。
# sysctl \ > net.ipv4.tcp_keepalive_time \ > net.ipv4.tcp_keepalive_intvl \ > net.ipv4.tcp_keepalive_probes net.ipv4.tcp_keepalive_time = 7200 net.ipv4.tcp_keepalive_intvl = 75 net.ipv4.tcp_keepalive_probes = 9 |
请注意sysctl名称与procfs路径非常接近。写入是使用-w开关执行的 sysctl (8)
# sysctl -w \ > net.ipv4.tcp_keepalive_time=600 \ > net.ipv4.tcp_keepalive_intvl=60 \ > net.ipv4.tcp_keepalive_probes=20 net.ipv4.tcp_keepalive_time = 600 net.ipv4.tcp_keepalive_intvl = 60 net.ipv4.tcp_keepalive_probes = 20 |
请注意,sysctl (8) 不使用 sysctl(2) 系统调用,而是直接在procfs子树中进行读写,因此您将需要procfs在内核中启用并在文件系统中挂载,就像您直接访问procfs接口中的文件一样。 Sysctl(8) 只是执行相同操作的另一种方式。
有几种方法可以在每次系统启动时重新配置系统。首先,请记住,每个 Linux 发行版都有自己的一组由 init (8) 调用的 init 脚本。最常见的配置包括/etc/rc.d/目录,或替代方案/etc/init.d/。在任何情况下,您都可以在任何启动脚本中设置参数,因为 keepalive 每次在其过程需要它们时都会重新读取这些值。因此,如果您更改了tcp_keepalive_intvl的值,当连接仍然建立时,内核将在未来使用新值。
有三个逻辑上应该放置初始化命令的位置:第一个是配置网络的位置,第二个是rc.local脚本,通常包含在所有发行版中,它被称为完成用户配置设置的位置。第三个位置可能已存在于您的系统中。回顾 sysctl (8) 工具,您可以看到-p开关从/etc/sysctl.conf配置文件加载设置。在许多情况下,您的 init 脚本已经执行 sysctl-p(您可以 "grep" 在配置目录中进行确认),因此您只需在/etc/sysctl.conf中添加行,以使它们在每次启动时加载。有关 sysctl.conf(5) 语法的更多信息,请参阅手册页。