专栏首页呆呆熊的技术路靓仔! 能跳出TIME-WAIT的坑吗

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

1. 开篇语

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

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

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

2. 搭建实验环境

为了方面模拟网络情况, 我们设置可用端口区间仅为81

sysctl -w "net.ipv4.ip_local_port_range=81 81"

3. 默认配置测试

访问本地nginx服务

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) 

验证时间

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

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状态图

参考资料:

https://vincent.bernat.ch/en/blog/2014-tcp-time-wait-state-linux#netipv4tcp_tw_reuse

本文分享自微信公众号 - 呆呆熊的技术路(gh_93f28f51010a)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-08-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Aria2一键安装管理脚本

    说明:Aria2作为一款linux下的下载神器,可以下载http资源、种子文件、磁力链接等,功能强大,就不过多介绍了。

    无道
  • 轻松掌握 Linux 命令(2):cd 命令

    花下猫语:熟练使用 Linux 系统绝对是程序员在职场的加分项,而 Linux 命令则是其中的关键。为了扩充本公众号的知识面,也为了自己能更加熟练地掌握 Lin...

    Python猫
  • 轻松掌握 Linux 命令(1):ls 命令

    ls 命令是 linux 下最常用的命令。ls 命令就是 list 的缩写,缺省下用来打印出当前目录的清单。如果 ls 指定其他目录,那么就会显示指定目录里的文...

    Python猫
  • 作为高级Java,你应该了解的Linux知识

    作为一个javaer,我以前写过很多关于Linux的文章。但经过多年的观察,发现其实对于大部分人,有些东西压根就用不着。用的最多的,就是到线上排查个问题而已,这...

    黄泽杰
  • 不想装系统,有没有办法在线体验 Linux?

    另外,这次分享还有承上启下的作用。承上是前几天挺受大家欢迎的《Android 手机如何改造成 Linux 服务器?》,启下是想预告:从明天开始,我会在每次发文的...

    Python猫
  • Docker入门(一)-- 基础概念与安装

    Docker最初是dotCloud公司的创始人Solomon Hyks在法国期间发起的一个公司内部项目,它是基于dotCloud公司多年云服务技术的一次革新,并...

    CodingDiray
  • 详解 Redis 内存管理机制和实现

    Redis是一个基于内存的键值数据库,其内存管理是非常重要的。本文内存管理的内容包括:过期键的懒性删除和过期删除以及内存溢出控制策略。

    黄泽杰
  • 轻松掌握 Linux 命令(3):pwd 命令

    花下猫语:熟练使用 Linux 系统绝对是程序员在职场的加分项,而 Linux 命令则是其中的关键。为了扩充本公众号的知识面,也为了自己能更加熟练地掌握 Lin...

    Python猫
  • Android 手机如何改造成 Linux 服务器?

    自从没有了学生身份之后,购买云服务器的价格是越来越贵了,不管是阿里云还是腾讯云。我寻思着能不能找到什么替代品,这让我想起之前在知乎不经意看到的,可以把 Andr...

    Python猫
  • 一文了解 Redis 内存监控和内存消耗

    Redis 是一种内存数据库,将数据保存在内存中,读写效率要比传统的将数据保存在磁盘上的数据库要快很多。所以,监控 Redis 的内存消耗并了解 Redis 内...

    黄泽杰

扫码关注云+社区

领取腾讯云代金券