什么是 TCP keepalive

TCP keepalive 概念很简单:当建立一个TCP连接时,会设置了一系列与该连接相关的定时器。其中有些定时器跟处理 keepalive 相关,在 keepalive 定时器倒计时变为零时,会给连接的另一方发送一个 keepalive 探针包(probe packet),包内没有数据且设置了 ACK 标识。

如果收到一个 keepalive 探针包的响应,说明连接是正常和有效的。TCP 可以处理只有协议头,但实际数据长度为零的数据包。这种机制是有用的,假如其他主机断开了连接,你可以及时注意到连接的断开。

如果 keepalive 探针没有响应,那么可以认为连接不是有效的,进而可以采取正确的操作。

TCP keepalive 的应用场景

KeepAlive 是非侵入性的,大多数情况下开启 keepalive 不会有其他风险。需要注意的是,这样做会带来额外的网络开销,例如会影响到路由器和防火墙。

  • 检测实际断掉的连接
  • 维持客户端与 NAT 间的活跃网络包

检测实际断掉的连接

设想 A、B 两端建有 TCP 连接:最开始是三次握手,A 发送 SYN 报文段给 B,B 响应 SYN/ACK 给 A,最后 A 发送 ACK 给 B。现在两端处于 established 状态,都在等待对方发送数据。如果此时 B 电源被拔掉,在没有发送任何数据的通知 A 的情况下,B 已经断开了连接。A 已经做好了准备接收数据,但不知道 B 已经宕机。之后 B 恢复供电并且系统重启,A 以为跟 B 的连接还是正常的。此时 A 试图给 B 发送数据,B 会回复 RST 包,这样 A 才关闭这个连接。

Keepalive 机制可以让 A 端避免出现上述的情况。实际上,如果连接双方有网络问题,keepalive 通过定时发送 keepalive 已经及时感知到连接断开。

    _____                                                     _____
   |     |                                                   |     |
   |  A  |                                                   |  B  |
   |_____|                                                   |_____|
      ^                                                         ^
      |--->--->--->-------------- SYN -------------->--->--->---|
      |---<---<---<------------ SYN/ACK ------------<---<---<---|
      |--->--->--->-------------- ACK -------------->--->--->---|
      |                                                         |
      |                                       system crash ---> X
      |
      |                                     system restart ---> ^
      |                                                         |
      |--->--->--->-------------- PSH -------------->--->--->---|
      |---<---<---<-------------- RST --------------<---<---<---|
      |                                                         |

维持客户端与 NAT 间的活跃网络包

keepalive 另一个用途是阻止因网络连接不活跃(长时间没有数据包)而导致的连接断开。

很多网络设备,尤其是NAT路由器,由于其硬件的限制(例如内存、CPU处理能力),无法保持其上的所有连接,因此在必要的时候会在连接池中选择一些不活跃的连接踢掉。典型做法是LRU,把最久没有数据的连接给踢掉。通过使用 TCP KeepAlive 机制,可以让连接每隔一小段时间就产生一些 ACK 包,以降低被踢掉的风险,当然,这样的代价是额外的网络和 CPU 负担。

    _____           _____                                     _____
   |     |         |     |                                   |     |
   |  A  |         | NAT |                                   |  B  |
   |_____|         |_____|                                   |_____|
      ^               ^                                         ^
      |--->--->--->---|----------- SYN ------------->--->--->---|
      |---<---<---<---|--------- SYN/ACK -----------<---<---<---|
      |--->--->--->---|----------- ACK ------------->--->--->---|
      |               |                                         |
      |               | <--- connection deleted from table      |
      |               |                                         |
      |--->- PSH ->---| <--- invalid connection                 |
      |               |                                         |

Linux 系统中的 keepalive

Linux 中跟 keepalive 相关的三个参数:

  • tcp_keepalive_time
  • tcp_keepalive_intvl
  • tcp_keepalive_probes

tcp_keepalive_time
发送最后一个数据包(只包含 ACK 的包不认为是数据包)和发送第一个 probe 包之间间隔的时间

tcp_keepalive_intvl
发送两个 keepalive probe 包之间间隔多长

tcp_keepalive_probes
连续发几个 probe 包不回复才认为连接断了

默认值

# 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

HTTP Keep-Alive是什么?如何工作?
TCP-Keepalive


sixsixfly
18 声望0 粉丝