Linux内核技术7 玩转网络配置之TCP断连

258 阅读3分钟
网络配置之TCP断连

TCP 断连的相关配置项
了解完了TCP连接的相关配置,我们再来探寻一下断连的相关配置。

四次挥手:

应用程序调用 close() 时,会向对端发送 FIN 包,然后会接收 ACK;对端也会调用 clsoe() 来发送 FIN,然后本端也会向对端回 ACK,这就是 TCP 的四次挥手过程。

首先调用 close() 的一侧是 active close(主动关闭);而接收到对端的 FIN 包后再调用 close() 来关闭的一侧,称之为 passive close(被动关闭)image.png

在四次挥手的过程中,我们需要格外关注三个 TCP 状态,就是上图中深红色的那三个状态:主动关闭方的 FIN_WAIT_2 和 TIME_WAIT,以及被动关闭方的 CLOSE_WAIT 状态。除了 CLOSE_WAIT 状态外,其余两个状态都有对应的系统配置项来控制。

1. tcp_fin_timeout 减少FIN_WAIT_2等待时间
FIN_WAIT_2 状态:
TCP 进入到这个状态后,如果本端迟迟收不到对端的 FIN 包,那就会一直处于这个状态,于是就会一直消耗系统资源,一般是由于对端服务器异常导致的。

Linux 为了防止这种资源的开销,设置了这个状态的超时时间 tcp_fin_timeout,默认为 60s,超过这个时间后就会自动销毁该连接。

Tips: 通常我们可以将该参数调小,来减少等待时间:

net.ipv4.tcp_fin_timeout = 2

2. tcp_max_tw_buckets 限制TW状态连接的个数
TIME_WAIT状态:
TIME_WAIT 状态存在的意义是:最后发送的这个 ACK 包可能会被丢弃掉或者有延迟,这样对端就会再次发送 FIN 包。所以维持 TIME_WAIT 状态一段时间,可以保障 TCP 连接正常断开。

TIME_WAIT 的默认存活时间在 Linux 上是 60s(TCP_TIMEWAIT_LEN),我们可以修改内核做些优化来减小该值,或者将该值设置为可通过 sysctl 来调节,另外系统也提供了参数可以限制该状态的最大个数:

net.ipv4.tcp_max_tw_buckets = 10000

3. tcp_tw_reuse 防止端口冲突

Client 关闭跟 Server 的连接后,也有可能很快再次跟 Server 之间建立一个新的连接,而由于 TCP 端口最多只有 65536 个,如果不去复用处于 TIME_WAIT 状态的连接,就可能在快速重启应用程序时,出现端口被占用而无法创建新连接的情况。所以建议你打开复用 TIME_WAIT 的选项:

net.ipv4.tcp_tw_reuse = 1

Tips: 建议关闭一下配置,以免发生NAT环境下的丢包问题:

net.ipv4.tcp_tw_recycle = 0

CLOSE_WAIT 状态
对CLOSE_WAIT 状态而言,系统中没有对应的配置项。但是该状态也是一个危险信号,如果这个状态的 TCP 连接较多,那往往意味着应用程序有 Bug,在某些条件下没有调用 close() 来关闭连接。

Tips: 如果你的系统中存在很多 CLOSE_WAIT 状态的连接,那你最好去排查一下你的应用程序,看看哪里漏掉了 close()。

TCP连接配置参数速查表

image.png