【每日一记11】+第5天:彻底弄懂TCP协议:从三次握手说起(五)
  

易逝的信仰 549

{{ttag.title}}
本帖最后由 易逝的信仰 于 2020-9-7 12:56 编辑

三、TIME_WAIT 会带来哪些问题呢?

TIME_WAIT 带来的问题注意是源于:一个连接进入 TIME_WAIT 状态后需要等待 2*MSL(一般是 1 到 4 分钟)那么长的时间才能断开连接释放连接占用的资源,会造成以下问题:

  • 作为服务器,短时间内关闭了大量的 Client 连接,就会造成服务器上出现大量的 TIME_WAIT 连接,占据大量的 tuple,严重消耗着服务器的资源。

  • 作为客户端,短时间内大量的短连接,会大量消耗的 Client 机器的端口,毕竟端口只有 65535 个,端口被耗尽了,后续就无法在发起新的连接了。



由于上面两个问题,作为客户端需要连本机的一个服务的时候,首选 UNIX 域套接字而不是 TCP)。TIME_WAIT 很令人头疼,很多问题是由 TIME_WAIT 造成的,但是 TIME_WAIT 又不是多余的不能简单将 TIME_WAIT 去掉,那么怎么来解决或缓解 TIME_WAIT 问题呢?可以进行 TIME_WAIT 的快速回收和重用来缓解 TIME_WAIT 的问题。有没一些清掉 TIME_WAIT 的技巧呢?

四、TIME_WAIT 的快速回收和重用

【1】TIME_WAIT 快速回收linux 下开启 TIME_WAIT 快速回收需要同时打开 tcp_tw_recycle 和 tcp_timestamps(默认打开)两选项。Linux 下快速回收的时间为 3.5* RTO(Retransmission Timeout),而一个 RTO 时间为 200ms 至 120s。开启快速回收 TIME_WAIT,可能会带来(问题一、)中说的三点危险,为了避免这些危险,要求同时满足以下三种情况的新连接要被拒绝掉:

  • 来自同一个对端 Peer 的 TCP 包携带了时间戳;

  • 之前同一台 peer 机器(仅仅识别 IP 地址,因为连接被快速释放了,没了端口信息)的某个 TCP 数据在 MSL 秒之内到过本 Server;

  • Peer 机器新连接的时间戳小于 peer 机器上次 TCP 到来时的时间戳,且差值大于重放窗口戳(TCP_PAWS_WINDOW)。



初看起来正常的数据包同时满足下面 3 条几乎不可能,因为机器的时间戳不可能倒流的,出现上述的 3 点均满足时,一定是老的重复数据包又回来了,丢弃老的 SYN 包是正常的。到此,似乎启用快速回收就能很大程度缓解 TIME_WAIT 带来的问题。但是,这里忽略了一个东西就是 NAT。

在一个 NAT 后面的所有 Peer 机器在 Server 看来都是一个机器,NAT 后面的那么多 Peer 机器的系统时间戳很可能不一致,有些快,有些慢。这样,在 Server 关闭了与系统时间戳快的 Client 的连接后,在这个连接进入快速回收的时候,同一 NAT 后面的系统时间戳慢的 Client 向 Server 发起连接,这就很有可能同时满足上面的三种情况,造成该连接被 Server 拒绝掉。所以,在是否开启 tcp_tw_recycle 需要慎重考虑了

【2】TIME_WAIT 重用

linux 上比较完美的实现了 TIME_WAIT 重用问题。只要满足下面两点中的一点,一个 TW 状态的四元组(即一个 socket 连接)可以重新被新到来的 SYN 连接使用。

[1]. 新连接 SYN 告知的初始序列号比 TIME_WAIT 老连接的末序列号大;[2]. 如果开启了 tcp_timestamps,并且新到来的连接的时间戳比老连接的时间戳大。

要同时开启 tcp_tw_reuse 选项和 tcp_timestamps 选项才可以开启 TIME_WAIT 重用,还有一个条件是:重用 TIME_WAIT 的条件是收到最后一个包后超过 1s。细心的同学可能发现 TIME_WAIT 重用对 Server 端来说并没解决大量 TIME_WAIT 造成的资源消耗的问题,因为不管 TIME_WAIT 连接是否被重用,它依旧占用着系统资源。即便如此,TIME_WAIT 重用还是有些用处的,它解决了整机范围拒绝接入的问题,虽然一般一个单独的 Client 是不可能在 MSL 内用同一个端口连接同一个服务的,但是如果 Client 做了 bind 端口那就是同个端口了。时间戳重用 TIME_WAIT 连接的机制的前提是 IP 地址唯一性,得出新请求发起自同一台机器,但是如果是 NAT 环境下就不能这样保证了,于是在 NAT 环境下,TIME_WAIT 重用还是有风险的。

有些同学可能会混淆 tcp_tw_reuse 和 SO_REUSEADDR 选项,认为是相关的一个东西,其实他们是两个完全不同的东西,可以说两个半毛钱关系都没。tcp_tw_reuse 是内核选项,而 SO_REUSEADDR 用户态的选项,使用 SO_REUSEADDR 是告诉内核,如果端口忙,但 TCP 状态位于 TIME_WAIT,可以重用端口。如果端口忙,而 TCP 状态位于其他状态,重用端口时依旧得到一个错误信息,指明 Address already in use”。如果你的服务程序停止后想立即重启,而新套接字依旧使用同一端口,此时 SO_REUSEADDR 选项非常有用。但是,使用这个选项就会有(问题二、)中说的三点危险,虽然发生的概率不大。

打赏鼓励作者,期待更多好文!

打赏
2人已打赏

新手229660 发表于 2020-9-8 09:08
  
感谢分享
伊利丹·怒风 发表于 2021-6-27 23:08
  
多谢楼主的分享,期待你的更多技术贴
伊利丹·怒风 发表于 2021-6-27 23:09
  
多谢楼主的分享,期待你的更多技术贴
yim 发表于 2021-12-18 10:30
  
发表新帖
热门标签
全部标签>
每日一问
2024年技术争霸赛
安装部署配置
技术笔记
产品连连看
每周精选
2023技术争霸赛专题
技术盲盒
干货满满
信服课堂视频
技术咨询
功能体验
自助服务平台操作指引
秒懂零信任
运维工具
文档捉虫活动
功能咨询
通用技术
GIF动图学习
新版本体验
问题分析处理
SDP百科
标准化排查
纪元平台
排障笔记本
畅聊IT
答题自测
专家问答
技术圆桌
测试报告
每日一记
用户认证
解决方案
VPN 对接
项目案例
地址转换
存储
技术争霸赛
卧龙计划
在线直播
MVP
网络基础知识
升级
安全攻防
上网策略
日志审计
流量管理
云计算知识
原创分享
sangfor周刊
SANGFOR资讯
专家分享
技术顾问
信服故事
终端接入
授权
设备维护
资源访问
虚拟机
迁移
加速技术
产品预警公告
玩转零信任
信服圈儿
S豆商城资讯
「智能机器人」
追光者计划
深信服技术支持平台
社区帮助指南
答题榜单公布
华北区拉练
天逸直播
以战代练
技术晨报
山东区技术晨报
齐鲁TV
华北区交付直播
北京区每日一练

本版版主

461
245
13

发帖

粉丝

关注

本版达人

feeling

本周分享达人

新手29676...

本周提问达人