服务器存在大量连接是TIME_WAIT状态

问题现象

云服务器中存在大量处于TIME_WAIT状态的连接。

TIME_WAIT是TCP连接关闭过程中的一个状态,具体是这么形成的:
1 主动关闭端A:发FIN,进入FIN-WAIT-1状态,并等待……
2 被动关闭端P:收到FIN后必须立即发ACK,进入CLOSE_WAIT状态,并等待……
3 主动关闭端A:收到ACK后进入FIN-WAIT-2状态,并等待……
4 被动关闭端P:发FIN,进入LAST_ACK状态,并等待……
5 主动关闭端A:收到FIN后必须立即发ACK,进入TIME_WAIT状态,等待2MSL后结束Socket
6 被动关闭端P:收到ACK后结束Socket

因此,TIME_WAIT状态是出现在主动发起连接关闭的一点,和是谁发起的连接无关,可以是client端,也可以是server端。

原因分析

首先通过调用close()发起主动关闭,在发送最后一个ACK之后会进入time_wait的状态,该发送方会保持2MSL时间之后才会回到初始状态。MSL值是数据包在网络中的最大生存时间。产生这种结果使得这个TCP连接在2MSL连接等待期间,定义这个连接的四元组(客户端IP地址和端口,服务端IP地址和端口号)不能被使用。

解决方法

通过netstatss命令,可以看到大量处于TIME_WAIT状态的连接。

  1. 执行以下命令,查看TIME_WAIT状态的连接数量。
    netstat -n | awk '/^tcp/ {++y[$NF]} END {for(w in y) print w, y[w]}'

    说明:或者执行ss -tan state time-wait命令,查看TIME_WAIT连接信息。

  2. 执行以下命令,编辑系统内核配置。
    vi /etc/sysctl.conf

    修改或加入以下内容。

    net.ipv4.tcp_syncookies = 1 
    net.ipv4.tcp_tw_reuse = 1 
    net.ipv4.tcp_tw_recycle = 1
    net.ipv4.tcp_fin_timeout = 30

    警告:对于服务端来说,在NAT环境中,开启net.ipv4.tcp_tw_recycle = 1配置可能导致校验时间戳递增,从而影响业务,不建议开启该功能。关于这四个内核参数的更多介绍,请参考以下内容:

    • net.ipv4.tcp_syncookies=1:开启SYN的cookies,当出现SYN等待队列溢出时,启用cookies进行处理。
    • net.ipv4.tcp_tw_reuse=1:允许将TIME-WAIT的socket重新用于新的TCP连接。如果新请求的时间戳,比存储的时间戳更大,则系统将会从TIME_WAIT状态的存活连接中选取一个,重新分配给新的请求连接。
    • net.ipv4.tcp_tw_recycle=1:开启TCP连接中TIME-WAIT的sockets快速回收功能。需要注意的是,该机制也依赖时间戳选项,系统默认开启tcp_timestamps机制,而当系统中的tcp_timestamps和tcp_tw_recycle机制同时开启时,会激活TCP的一种行为,即缓存每个连接最新的时间戳,若后续的请求中时间戳小于缓存的时间戳时,该请求会被视为无效,导致数据包会被丢弃。特别是作为负载均衡服务器的场景,不同客户端请求经过负载均衡服务器的转发,可能被认为是同一个连接,若客户端的时间不一致,对于后端服务器来说,会发生时间戳错乱的情况,因此会导致数据包丢失,从而影响业务。
    • net.ipv4.tcp_fin_timeout=30:如果socket由服务端要求关闭,则该参数决定了保持在FIN-WAIT-2状态的时间。
  3. 执行命令以下命令,使配置生效。
    /sbin/sysctl -p
  4. TIME_WAIT状态的连接较多时,会导致各种问题,除了直观的减少TIME_WAIT状态的连接,也可以通过扩大端口范围和对TIME_WAIT的bucket进行扩容等手段优化系统性能。

本文来自投稿,不代表程序人生-爱否编程,if programmer立场,如若转载,请注明出处:https://www.if98.com/328131696/blog/linux/1911.html

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

公司战略调整:专注云产品的同时研发云方案、云技术;欢迎行业大枷入驻云技术社区,共创未来。产品管理请访问:yun.byun.com