1. time_wait状态如何产生? 前端
由上面的变迁图,首先调用close()发起主动关闭的一方,在发送最后一个ACK以后会进入time_wait的状态,也就说该发送方会保持2MSL时间以后才会回到初始状态。MSL值得是数据包在网络中的最大生存时间。产生这种结果使得这个TCP链接在2MSL链接等待期间,定义这个链接的四元组(客户端IP地址和端口,服务端IP地址和端口号)不能被使用。缓存
2.time_wait状态产生的缘由cookie
1)为实现TCP全双工链接的可靠释放网络
由TCP状态变迁图可知,假设发起主动关闭的一方(client)最后发送的ACK在网络中丢失,因为TCP协议的重传机制,执行被动关闭的一方(server)将会重发其FIN,在该FIN到达client以前,client必须维护这条链接状态,也就说这条TCP链接所对应的资源(client方的local_ip,local_port)不能被当即释放或从新分配,直到另外一方重发的FIN达到以后,client重发ACK后,通过2MSL时间周期没有再收到另外一方的FIN以后,该TCP链接才能恢复初始的CLOSED状态。若是主动关闭一方不维护这样一个TIME_WAIT状态,那么当被动关闭一方重发的FIN到达时,主动关闭一方的TCP传输层会用RST包响应对方,这会被对方认为是有错误发生,然而这事实上只是正常的关闭链接过程,并不是异常。socket
确保被动关闭方收到ACK,链接正常关闭,且不因被动关闭方重传FIN影响下一个新链接tcp
2)为使旧的数据包在网络因过时而消失spa
为说明这个问题,咱们先假设TCP协议中不存在TIME_WAIT状态的限制,再假设当前有一条TCP链接:(local_ip, local_port, remote_ip,remote_port),因某些缘由,咱们先关闭,接着很快以相同的四元组创建一条新链接。本文前面介绍过,TCP链接由四元组惟一标识,所以,在咱们假设的状况中,TCP协议栈是没法区分先后两条TCP链接的不一样的,在它看来,这根本就是同一条链接,中间先释放再创建的过程对其来讲是“感知”不到的。这样就可能发生这样的状况:前一条TCP链接由local peer发送的数据到达remote peer后,会被该remot peer的TCP传输层当作当前TCP链接的正常数据接收并向上传递至应用层(而事实上,在咱们假设的场景下,这些旧数据到达remote peer前,旧链接已断开且一条由相同四元组构成的新TCP链接已创建,所以,这些旧数据是不该该被向上传递至应用层的),从而引发数据错乱进而致使各类没法预知的诡异现象。做为一种可靠的传输协议,TCP必须在协议层面考虑并避免这种状况的发生,这正是TIME_WAIT状态存在的第2个缘由。server
2MSL:报文最大生存时间,确保旧的数据不会影响新链接blog
3)总结
具体而言,local peer主动调用close后,此时的TCP链接进入TIME_WAIT状态,处于该状态下的TCP链接不能当即以一样的四元组创建新链接,即发起active close的那方占用的local port在TIME_WAIT期间不能再被从新分配。因为TIME_WAIT状态持续时间为2MSL,这样保证了旧TCP链接双工链路中的旧数据包均因过时(超过MSL)而消失,此后,就能够用相同的四元组创建一条新链接而不会发生先后两次链接数据错乱的状况。队列
方法:
net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_fin_timeout = 30
3.而后执行/sbin/sysctl -p让参数生效。
net.ipv4.tcp_syncookies = 1表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少许SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1表示开启重用。容许将TIME-WAIT sockets从新用于新的TCP链接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1表示开启TCP链接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout 修改系統默认的TIMEOUT时间
修改以后,再用命令查看TIME_WAIT链接数netstat -ant |grep “TIME_WAIT” |wc –l。在没有nat状况下还须要设置net.ipv4.tcp_timestamps = 1才能生效。关于tcp_tw_recycle参数,TCP有一种行为,能够缓存每一个链接最新的时间戳,后续请求中若是时间戳小于缓存的时间戳,即视为无效,相应的数据包会被丢弃。Linux是否启用这种行为取决于tcp_timestamps和tcp_tw_recycle,由于tcp_timestamps缺省就是开启的,因此当tcp_tw_recycle被开启后,实际上这种行为就被激活了。在nat环境中会出现时间戳错乱的状况,后面的数据包就被丢弃了,具体的 表现一般是是客户端明明发送的SYN,但服务端就是不响应ACK。由于NAT设备将数据包的源IP地址都改为了一个地址(或者少许的IP地址),可是却基本上不修改TCP包的时间戳,则会致使时间戳混乱。建议:若是前端部署了三/四层NAT设备,尽可能关闭快速回收,以避免发生NAT背后真实机器因为时间戳混乱致使的SYN拒绝问题。
net.ipv4.tcp_tw_reuse = 1
若是能保证如下任意一点,一个TW状态的四元组(即一个socket链接)能够从新被新到来的SYN链接使用:
1.初始序列号比TW老链接的末序列号大2.若是使能了时间戳,那么新到来的链接的时间戳比老链接的时间戳大