关于作者
前滴滴出行技术专家,现任OPPO文档数据库mongodb负责人,负责oppo千万级峰值TPS/十万亿级数据量文档数据库mongodb内核研发及运维工作,一直专注于分布式缓存、高性能服务端、数据库、中间件等相关研发。后续持续分享《MongoDB内核源码设计、性能优化、最佳运维实践》,Github账号地址:https://github.com/y123456yz
1. time_wait状态产生条件
只有在正常四次挥手关闭连接的情况下,在主动关闭连接的一方会出现一段时间的time_wait。如果启用了快速回收功能,回收时间和网络延迟状况有关,正常情况下小于1s,如果没有开启time_wait快速回收功能,则time_wait回收时间默认60s。
三次挥手过程(FIN+ACK, FIN+ACK,ACK)的情况,例如杀掉一段进程,第一个发送FIN+ACK的一端也会产生time_wait。
2. Time_wait状态相关参数说明
TCP中有和time_wait状态相关的参数有以下四个:
tcp_tw_recycle | 表示开启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快速回收
3.1 快速回收功能失效前提
Time_wait快速回收功能生效前提:启用tcp_tw_recycle,并启动本端和对端tcp_timestamps配置。启用timestamps功能时,报文中会携带时间戳选项信息,抓包如下:
![6b7ea6febde69ed357441e81412c8181.png](https://i-blog.csdnimg.cn/blog_migrate/f7ab144aee9e91d3f09cacd29947b437.png)
3.2 启用time_wait快速回收功能副作用
如果启用了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地址了。
3.3内核协议栈相关主要源码
Time_wait状态生成及快速回收相关代码:
![3911a3b55476e48075407783e34229d7.png](https://i-blog.csdnimg.cn/blog_migrate/3d074ab763811978e9c235e5856d2b30.png)
![7d1bb1d4d5c4d301098a73a72c7cdced.png](https://i-blog.csdnimg.cn/blog_migrate/3af82a2956b455b4d1b67a77e19f047c.png)
![a59a0f2cb456660794b68aee0bfed4ff.png](https://i-blog.csdnimg.cn/blog_migrate/76f9a11a50722bf66b65aadbe1bc900c.png)
![08e463f3a15c33aea8511119ba2c2c4d.png](https://i-blog.csdnimg.cn/blog_migrate/e0b562ecbeaabff573c8d611b14458e4.png)
![ef078d7c0a8cd81e005f8a147e48d526.png](https://i-blog.csdnimg.cn/blog_migrate/80f5476357d57a02d118ca1fdc30b47c.png)
开启timestamps引起的丢包相关源码如下:
![b20263ca4cac094860566bc3f5f15815.png](https://i-blog.csdnimg.cn/blog_migrate/f0b143b8458fef083ba35dd23866e2bc.png)
4. 客户端端口重用
4.1 客户端大量time_wait,端口重用前提
启用tcp_tw_reuse,并启动本端和对端tcp_timestamps配置。
4.2 内核协议栈相关主要源码
![a098c3ca26ea6a3a7515ccb6ffc3ff03.png](https://i-blog.csdnimg.cn/blog_migrate/5bdefb39cda270226cea691e98e3d460.png)
![fbf66a865fddacc6cfe01724b04189d3.png](https://i-blog.csdnimg.cn/blog_migrate/685ecd8fc67003b684fcb7ff112196a2.png)
![8c933dea50a288ea69ca03c691158d14.png](https://i-blog.csdnimg.cn/blog_migrate/e3328d7626a5feb961d372928994a471.jpeg)
5. 大量timewait对客户端、服务端影响
5.1 客户端大量time_wait影响
- 大量time_wait会造成连接资源不释放,内存无法回收。
- 由于客户端端口一般采用协议栈随机分配的方式,协议栈会给每个客户端连接分配一个未使用的端口,因此如果客户端同一IP对应的time_wait数量超过ip_local_port_range设置的最大值(也就是65000),端口将被用完,连接会无法建立。
5.2 服务端大量time_wait影响
由于服务端只占用监听端口,因此不存在端口用完的现象。服务端大量time_wait唯一影响是:资源不释放,内存无法回收。
6. 测试验证
本次测试结果采用sysbench.short来压测cobar来验证,客户端物理设备和服务端物理设备的ip_local_port_range(1024~65000)和tcp_max_tw_buckets(81920)参数都是默认值,测试结果如下:
- 当cobar服务端time_wait数达到81920的时候,任然可以继续接收客户端连接,能够正常提供连接服务。
- 当客户端测试工具sysbench.short服务器上的time_wait数达到60000多的时候,客户端连接失败,无法连接,因为端口用完。打印:Cannot assign requested address; Cobar服务器time_wait超限时打印:
![dccf1bf6572c7baf2ac0a1361627c116.png](https://i-blog.csdnimg.cn/blog_migrate/4f188c6e53affa85ee7f68f780eb3e42.jpeg)
Cobar服务器time_wait超限的情况下,客户端sysbench压测结果基本不受影响,如下:
![259253083f358ee0b63fdcd25489f5c0.png](https://i-blog.csdnimg.cn/blog_migrate/617b2d843856073dd6338b7b68fbb5eb.jpeg)
从上面测试可以看出,服务端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协议规范应急的处理,立竿见影。建议这种。 |