靓仔, 能跳出TIME-WAIT的坑吗

1. 开篇语

在TCP断开链接四次挥手时, 主动发起关闭方会产生 TIME_WAIT, TIME_WAIT 是 TCP 协议可靠性设计的重要一个环节, 虽然说加强了可靠性, 可是对于高并发场景下, 会产生大量的 TIME_WAIT, 致使高峰时段无故口能够使用.html

本文只作简单学习测试, 不保证内容的全面性及正确性, 不要轻易修改正式环境内核配置linux

今天主要对两个 Linux 内核的配置 tcp_tw_reuse 和 tcp_tw_recycle 进行测试讲解nginx

2. 搭建实验环境

为了方面模拟网络状况, 咱们设置可用端口区间仅为81安全

sysctl -w "net.ipv4.ip_local_port_range=81 81"
复制代码

3. 默认配置测试

访问本地nginx服务bash

curl http://127.0.0.1

curl http://127.0.0.1
curl: (7) Failed to connect to 127.0.0.1: Cannot assign requested address
复制代码

查看网络状态服务器

netstat -napo |grep 127.0.0.1
复制代码

咱们能够看到, 第一次正常, 在 2MSL 时间内, 再次访问将会出现没法分配请求地址错误. 在 Linux 中TIME_WAIT时间为60s,而且还没法修改网络

TIME_WAIT过时时间宏定义并发

//include/net/tcp.h
/* how long to wait to destroy TIME-WAIT
 * state, about 60 seconds   */
#define TCP_TIMEWAIT_LEN (60*HZ) 
复制代码

验证时间 curl

能够看到标红线的地方为 time_wait 的倒计时,到时间后将会自动释放端口.socket

4. 关于 TIME_WAIT 状况的配置指令

开启 tcp_tw_reuse

echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
复制代码

进行测试

咱们能够观测到, 在 TIME_WAIT 状态的端口也能够继续完成请求, 但不会改变 TIME_WAIT 自己的状态和计时.

此结论证实, 当本地端口将耗尽时, 能够尝试开启 tcp_tw_reuse 进行端口重用.

It's not SO_REUSEADDR socket option. SO_REUSEADD is used for binding socket to LISTEN state even if it is in TIME_WAIT state.

开启 tcp_tw_recycle

开启 tcp_tw_recycle

echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle 
复制代码

进行测试

结果很好, 一样完成了请求测试. 可是彷佛跟 tcp_tw_reuse 哪里不太同样?

对比开启 tcp_tw_reuse 的netstat检测结果, 看看有什么差别.

咱们发现这里简直就是暴力美学, 根本没有 TIME_WAIT 的状态呀

linux内核断定代码

当开启回收时,咱们的 timeout 值为 rto, 这是一个很是短的一个时间, 不然为 TCP_TIMEWAIT_LEN , 还记得文章开头提到的宏定义的时间吗, 没错, 这里指的就是那个60s.

5. tcp_tw_reuse 与 tcp_tw_recycle 的区别

彷佛这两个参数都可以很好的工做, 至少测试结果是很理想的.

参数 功能
tcp_tw_reuse 复用(reuse),不改变 TIMEWAIT 状态
tcp_tw_recycle 回收(recycle),最快时间回收

net.ipv4.tcp_timestamps 默认开启, 他是记录标记时间戳

tcp_tw_reuse 是怎么工做的

若是开启了 tcp_tw_reuse, 若是客户端发来的时间戳大于先前链接内核记录的最新时间戳, 则 Linux 将从新使用状态中的现有链接以 TIME-WAIT 用于新的对外请求链接, 状态中的传出链接 TIME-WAIT可在仅一秒以后重复使用.

tcp_tw_recycle 是怎么工做的

若是开启了 tcp_tw_recycle, 则内核会记住客户端上次发来数据包的时间戳, 若是发来的数据包时间戳小于内核记录的最后发来的数据包时间戳, 那么将会丢弃此数据包, 这种状况在 NAT 模式下多机器时间滞后或同时发送, 会有很大危险, 会形成难以排查的异常状况.

网上说 设置net.ipv4.tcp_timestamps=0, 能够再也不检测时间戳, 未找到官方出处, 真实性没法保证.

6. 结论:

在服务器端,请勿启用net.ipv4.tcp_tw_recycle 除非你很是肯定你的服务中永远不会有NAT设备。 启用net.ipv4.tcp_tw_reuse 对于发送请求 (outgoing connection) 的链接有效。

在客户端,启用 net.ipv4.tcp_tw_reuse 是另外一个几乎安全的解决方案

并且,在设计协议时,不要先让客户关闭。客户端没必要处理将TIME-WAIT状态推向更适合处理此问题的服务器的状态。

因此最终建议能够开启 tcp_tw_reuse, 禁用 tcp_tw_recycle.

7. 附TCP状态图

参考文档:

vincent.bernat.ch/en/blog/201…

linuxsyseng.blogspot.com/2017/03/the…

更多精彩技术, 请关注公众号 (呆呆熊的技术路):

相关文章
相关标签/搜索