问题场景
线上服务器使用nginx 做反向代理,访问链路:client -> nginx -> 服务器,在nginx 上经常出现大量的 time_wait 连接。
怎么查看 time_wait 连接
-
使用netstat
# netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
-
使用ss命令
# ss -S
什么是 time_wait 连接
TCP连接关闭.png通过上图,我们可以看到 TIME_WAIT 状态是在tcp断开链接时产生的,因为TCP连接是双向的,所以在关闭连接的时候,两个方向各自都需要关闭。
先发FIN包的一方执行的是主动关闭;后发FIN包的一方执行的是被动关闭。主动关闭的一方会进入 TIME_WAIT 状态,并且在此状态停留两倍的MSL时长。MSL指的是报文段的最大生存时间,如果报文段在网络活动了MSL时间,还没有被接收,那么会被丢弃。
关于MSL的大小,RFC 793协议中给出的建议是两分钟,不过实际上不同的操作系统可能有不同的设置,以Linux为例,通常是半分钟,两倍的MSL就是一分钟,也就是60秒,并且这个数值是硬编码在内核中的,也就是说除非你重新编译内核,否则没法修改它。
-
为什么需要等待2MSL?
-
当TCP执行主动关闭,并发送最后一个ACK,在TIME_WAIT状态停留的时间为2倍的MSL,这样可以让TCP可以有时间再次发送最后一个ACK,防止丢失(另一端超时并重发最后的FIN)
-
在发送完ACK报文段后,再经过2MSL时间,就可以使本连接持续的时间所产生的所有报文段都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求的报文段
-
-
time_wait 连接过多的危害?
在socket的 TIME_WAIT 状态结束之前,该socket所占用的本地端口号将一直无法释放。在高并发并且采用短连接方式进行交互的系统中运行一段时间后,系统中就会存在大量的time_wait状态,如果time_wait状态把系统所有可用端口,都占完了且尚未被系统回收时,就会出现无法向服务端创建新的socket连接的情况。
如何优化 time_wait 过多的问题?
- 调整内核参数
编辑 /etc/sysctl.conf 文件
使用# 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭; net.ipv4.tcp_tw_reuse = 1 # 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭,但是不建议开启,在NAT环境下,开启可能会引起问题。 net.ipv4.tcp_tw_recycle = 0 # 表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。 net.ipv4.tcp_max_syn_backlog = 8192
sysctl -p
命令,使配置生效。
网友评论