转载自:http://blog.sina.com.cn/s/blog_64e21d220102xb8m.html
如果在有大量并发的短链接情况下,服务器上的 TIME_WAIT 状态会很多,这会消耗很多系统资源。只要在网络上搜索一下,你就会发现,处理方式差不多都是设置两个参数:一个叫tcp_tw_reuse,另一个叫tcp_tw_recycle的参数。本文主要讨论这两个参数带来的副作用。
从状态机图上可以看出,只有主动关闭连接方有TIME_WAIT状态,被关闭方没有该状态。正常情况下,系统会在TIME_WAIT状态等待2MSL(Maximum Segment Lifetime),也就是4MIN(RFC 793中规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等),MSL是一个数据包在网络上能生存的最长生命周期,一旦超过MSL的包就会被丢弃。
为什么要这有TIME_WAIT?主要有两个原 因:1、TIME_WAIT确保有足够的时间让对端收到了ACK,如果被动关闭的那方没有收到ACK,就会触发被动端重发FIN,一来一去正好2个 MSL,2、有足够的时间让这个连接不会跟后面的连接混在一起(你要知道,有些自做主张的路由器会缓存IP数据包,如果连接被重用了,那么这些延迟收到的 包就有可能会跟新连接混在一起)。可以看看这篇文章《TIME_WAIT and its design implications for protocols and scalable client server systems》。附图:
设想一下,如果没有TIME_WAIT,主动关闭方发送最后的FIN包后里面关闭连接,如果由于网络原因,最后发出的FIN包没有顺利到达被动关闭方(此时的被动关闭方一直处于LAST_ACK状态等待最后FIN),被动关闭方长时间没有接收到FIN包,会认为之前由被动关闭方发出的ACK/FIN包client没有收到,被动关闭方会重新发送一个ACK/FIN包,这时候主动关闭方收到ACK/FIN包,发现端口已经关闭,协议栈直接回复RST包,导致被动关闭方端接收到RST包报错,影响应用进程。
所以 TIME_WAIT 的作用可以保证最后的ACK包必然能到达对方,确保最后的连接正常端口。
但是TIME_WAIT是占资源的,包括端口资源,协议栈队列,所以大量的TIME_WAIT会影响socket建立新连接。
但是如何解决TIME_WAIT过多的问题呢:
同时打开net.ipv4.tcp_tw_recycle和net.ipv4.tcp_timestamps 或者 同时打开net.ipv4.tcp_timestamps和net.ipv4.tcp_tw_reuse。
系统既然默认是关闭tcp_tw_recycle和tcp_tw_reuse的,肯定有原因!这很有可能会引发未知的TCP错误,而且很诡异,很难排查。
一、net.ipv4.tcp_tw_recycle
功能:系统会假设对端开启了 tcp_timestamps,然后会去比较时间戳,如果时间戳变大了,就可以重用fd。开启后在 3.5*RTO 内回收,RTO 200ms~ 120s 具体时间视网络状况。内网状况比tw_reuse 稍快,公网尤其移动网络大多要比tw_reuse 慢,优点就是能够回收服务端的TIME_WAIT数量
打开后的副作用:如果对端是一个NAT网络的话(如:一个公司只用一个IP出公 网)或是对端的IP被另一台重用了,或者一个机器上多个docker Node,这个事就复杂了。建链接的SYN可能就被直接丢掉了(你可能会看到connection time out的错误) -- 这就是为什么一个公司连接在测试服务器时,会很慢,但是服务器本身负载很低的问题的原因。
建议:对外服务器不能打开该开关!!!对内服务器如果没有docker(Nat转换)的可以打开。
二、net.ipv4.tcp_timestamps
功能:记录数据包的发送时间,其为双向的选项,当一方不开启时,两方都将停用timestamps,默认打开
打开后的副作用:1.10字节的TCP header开销 2. allow you to guess the uptime of a target system
建议:保持打开状态
三、net.ipv4.tcp_tw_reuse
功能:表示开启重用。当从协议认为安全,则允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭。 协议什么情况下认为是安全的?从代码来看是收到最后一个包后超过1s :(sysctl_tcp_tw_reuse && get_seconds() - tcptw->tw_ts_recent_stamp > 1)
打开后的副作用:主动关闭方有可能在下次使用时收到上一次连接的数据包,包括关闭连接响应包或者正常通信的数据包(因为数据包需要经过MSL时间才会消失),主动关闭方会出现奇怪的表现。
建议:服务器应该打开该配置,因为内网网络状态一般比较好。