MSL是Maximum Segment Lifetime英文的缩写,中文可以译为“报文最大生存时间”.
2MSL在RFC 793协议中给出的建议是两分钟, 但是在Linux下一般时30秒, 也就是说2MSL就是60秒.
CLOSE_WAIT是被动关闭连接是形成的,根据TCP状态机,服务器端收到客户端发送的FIN,TCP协议栈会自动发送ACK,连接进入CLOSE_WAIT状态。但如果服务器端不执行SOCKET的CLOSE()操作,状态就不能由CLOSE_WAIT迁移到LAST_ACK,则系统中会存在很多CLOSE_WAIT状态的连接.
所以如果被动关闭端关闭SOCKET不及时, 例如: I/O线程被意外阻塞,或者I/O线程执行的用户自定义Task比例过高,导致I/O操作处理不及时,链路不能被及时释放.
通常,CLOSE_WAIT 状态在服务器停留时间很短,如果你发现大量的 CLOSE_WAIT 状态,那么就意味着被动关闭的一方没有及时发出 包,一般有如下可能:
(1) 程序问题:如果代码层面忘记了 CLOSE 相应的 socket 连接,那么自然不会发出 FIN 包,从而导致 CLOSE_WAIT 累积;或者代码不严谨,出现死循环之类的问题,导致即便后面写了 CLOSE 也永远执行不到。
(2) 响应太慢或者超时设置过小:如果连接双方不和谐,一方不耐烦直接 timeout,另一方却还在忙于耗时逻辑,就会导致 close 被延后。响应太慢是首要问题,不过换个角度看,也可能是 timeout 设置过小。
简单说timewait之所以等待2MSL的时长,是为了避免因为网络丢包或者网络延迟而造成的tcp传输不可靠,而这个TIME_WAIT状态则可以最大限度的提升网络传输的可靠性。
同时TCP一般会禁止处于TIME_WAIT的连接上重建一个新的TCP连接, 这样做主要是为了避免新旧数据包出现串包的情况, 所以总结来说, TIME_WAIT的作用如下:
为实现TCP全双工连接的可靠释放为使旧的数据包在网络因过期而消失查看状态为TIME_WAIT的TCP连接。
$ netstat -tan |grep TIME_WAIT
统计TCP各种状态的连接数。
$ netstat -n | awk '/^tcp/ {++S[$NF]} END {for(i in S) print i, S[i]}'
方式一: 调整系统内核参数net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
或者将MSL值缩减, linux中MSL的值默认为60s,我们可以通过缩减MSL值来使得主动关闭连接一端由TIME_WAIT状态到关闭状态的时间减少。
但是这样做会导致延迟报文无法清除以及主动关闭连接一端不能收到重传来的FIN请求,也会影响很多基于TCP的应用的连接复用和调优。
所以在实际生产环境中,需要谨慎操作。
$ cat /proc/sys/net/ipv4/tcp_fin_timeout
$echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
或者$ vim /etc/sysctl.con
fnet.ipv4.tcp_fin_timeout = 30
优化完内核参数后,可以执行sysctl -p
命令,来激活上面的设置永久生效
短连接 连接->传输数据->关闭连接 HTTP是无状态的,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。 也可以这样说:短连接是指SOCKET连接后发送后接收完数据后马上断开连接。长连接 连接->传输数据->保持连接 -> 传输数据-> 。。。->关闭连接。 长连接指建立SOCKET连接后不管是否使用都保持连接,但安全性较差。
从区别上可以看出,长连接比短连接从根本上减少了关闭连接的次数,减少了TIME_WAIT状态的产生数>量,在高并发的系统中,这种方式的改动非常有效果,可以明显减少系统TIME_WAIT的数量。
我们可以在客户端将HTTP请求头里connection的值设置为:keep-alive。将短连接改成长连接。
长连接比短连接从根本上减少了server去主动关闭连接的次数,减少了TIME_WAIT状态连接的产生。
在利用nginx做反向代理时,如果要设置成长连接,则需要设置成:
1.从client到nginx的连接是长连接。
2.从nginx到server的连接是长连接。
原创声明,本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 本站 删除。