0. 手把手教你作中间件、高性能服务器、分布式存储技术交流群nginx
手把手教你作中间件、高性能服务器、分布式存储等(redis、memcache、nginx、大容量redis pika、rocksdb、mongodb、wiredtiger存储引擎、高性能代理中间件),git地址以下:git
git地址:https://github.com/y123456yz/middleware_development_learninggithub
1. time_wait状态产生条件redis
只有在正常四次挥手关闭链接的状况下,在主动关闭链接的一方会出现一段时间的time_wait。若是启用了快速回收功能,回收时间和网络延迟情况有关,正常状况下小于1s,若是没有开启time_wait快速回收功能,则time_wait回收时间默认60s。mongodb
三次挥手过程(FIN+ACK, FIN+ACK,ACK)的状况,例如杀掉一段进程,第一个发送FIN+ACK的一端也会产生time_wait。服务器
2. Time_wait状态相关参数说明网络
TCP中有和time_wait状态相关的参数有如下四个:socket
tcp_tw_recycletcp |
表示开启TCP链接中time_wait的快速回收功能,默认为0,表示关闭;生效前提是必须启用本端和对端tcp_timestamps配置。分布式 |
tcp_timestamps |
时间戳选项,只有在该选项置1的时候tcp_tw_recycle才会生效。 |
tcp_max_tw_buckets |
表示系统同时保持time_wait的最大数量,若是超过这个量,time_wait将打印警告信息。超限的时候后面产生的time_wait直接不处理,释放资源。注意:是新的链接直接释放资源,老的链接仍是处于time_wait状态。 |
Tcp_tw_reuse |
客户端大量time_wait状态存在时,端口被占用,当有新的链接,若是没有可用端口,则会链接失败。启用该功能后,能够复用time_wait状态的链接。客户端tcp_tw_reuse生效前提是启用本端和对端tcp_timestamp。
Tcp_tw_reuse端口重用功能通常只针对客户端,由于服务端通常都是监听固定端口,端口数是固定的,端口不会用完。而客户端每次链接端口通常都是由协议栈自动分配。 |
3. Time_wait快速回收
Time_wait快速回收功能生效前提:启用tcp_tw_recycle,并启动本端和对端tcp_timestamps配置。启用timestamps功能时,报文中会携带时间戳选项信息,抓包以下:
若是启用了tcp_tw_recycle和tcp_timestamps,若是接收报文四层选项字段带有时间戳信息,则会对时间戳进行检查,对不知足条件的包会直接丢弃,可能会形成客户端链接创建不成功。例如网络路由信息反复变化,移动cmwap网络发来的包的时间戳乱跳,同一局域网经过路由器作NAT访问服务器(由于作NAT后,源IP就变为路由器的IP了,若是局域网内各个电脑系统时间不一致,则会出现)等状况有可能会出现部分链接异常。缘由是tcp_tw_recycle/tcp_timestamps以及对端tcp_timestamps都开启的条件下,60s内同一源ip主机的socket connect请求中的timestamp必须是递增的。不一样主机通过路由器作NAT后,报文的源IP地址就变为路由器的IP地址了。
Time_wait状态生成及快速回收相关代码:
开启timestamps引发的丢包相关源码以下:
4. 客户端端口重用
启用tcp_tw_reuse,并启动本端和对端tcp_timestamps配置。
5. 大量timewait对客户端、服务端影响
因为服务端只占用监听端口,所以不存在端口用完的现象。服务端大量time_wait惟一影响是:资源不释放,内存没法回收。
6. 测试验证
本次测试结果采用sysbench.short来压测cobar来验证,客户端物理设备和服务端物理设备的ip_local_port_range(1024~65000)和tcp_max_tw_buckets(81920)参数都是默认值,测试结果以下:
Cobar服务器time_wait超限的状况下,客户端sysbench压测结果基本不受影响,以下:
从上面测试能够看出,服务端time_wait不会影响客户端建链,只是占用内存。若是是客户端出现大量time_wait状态,此时端口用完,则没法创建链接。以上测试结论符合理论、代码分析。
7. 三种解决time_wait方法总结
|
Time_wait快速回收 |
端口重用 |
限制Tcp_max_tw_buckets |
配置方法 |
在须要进行time_wait快速回收的一端进行一下配置: tcp_tw_recycle:1 本端tcp_timestamps:1 对端tcp_timestamps:1 |
在须要进行time_wait快速回收的一端进行一下配置: tcp_tw_reuse:1 本端tcp_timestamps:1 对端tcp_timestamps:1 |
配置Tcp_max_tw_buckets 的值在60000如下。例如配置为30000 |
反作用 |
在某些状况下可能引发用户建链接失败(例如须要直接返回给用户信息的服务器) 比较暴力,不符合TCP协议规范 |
在某些状况下可能引发用户建链接失败(例如须要直接返回给用户信息的服务器) 部署复杂,须要同时改服务端,而服务端比较多。 服务器时间戳会带出IDC,通过中间各类网络设备,尤为是运营商的无线设备等,若是某个设备对时戳有校验,则会产生丢包问题。 |
比较暴力,不符合TCP协议规范 应急的处理,立竿见影。 建议这种。 |