大历史下的 tcp:恼人的 timewait

tcp timewait 是个恼人的状态,它的恶心自两类恶心的询问,oncall 和面试。大概诸如 “如何减少 timewait socket 数量”,“tw_reuse 和 tw_recycle …”,如果只为应用,用 reset 关连接就够了。

timewait 状态的根本目的是 “防止旧连接的报文干扰复用相同四元组的新连接”。

由于所有 tcp 连接完全复用相同的平坦的 32bit 序列号空间,所有 tcp 连接的序列号就在这 32bit 空间绕来绕去,如何区别报文所属的连接以及连接内所属的位置就是个问题。

连接内部序列号回绕好说,限制 wscale 最大 14 即可约束 tcp window 不超过 1/4 个序列号空间(请参考 rfc1323 和 linux before,after 宏),足以区分了。而为了在连接间区别序列号,tcp 内置了 timewait 状态,在关闭连接时等待足够的时间后才能复用相同四元组创建新连接,这段时间足够久,以至于任何旧连接的报文在网络上死的透透的。

linux tcp timewait 等待时间为 60s,这时间太久,大多数短视频都播完了。

事实上 wscale-max 已经足够好,linux timewait 这 60s 也已经够短,但还不够,于是借助 rfc1323 timestamps 选项的 paws 被标准化。为此优化效果,linux 又有 tcp_tw_reuse 和 tcp_tw_recycle 配置选项,但这些选项又太复杂,必须听专家的:“It should not be changed without advice/request of technical experts.” 且默认又不开启,显然绝大部分好学成性的程序员就给这些 technical experts 找了不少麻烦。

说到底,为什么 tcp_tw_reuse 默认不开启呢?因为它相当于取消了 timewait 状态并可以立马复用相同四元组新建连接,该四元组旧连接迟到报文如果且恰恰命中 window(32bit 说大不大,命中不难),就会污染新连接,至于新建连接时对端 lastack 状态等 last ack 却等来个 syn 倒是次要,如果序列号空间是 128bit,就算 lastack 等来个 syn 又如何,正常建连就是了。

核心还是无法区别一个序列号属于哪个连接。tcp 用 timewait 状态解决这问题是一个非常拙劣的手法,说实在的就是 “搞不定就等一段时间”。这种手段如何 low 到被喷,我举个例子。在我们写内核模块时,卸载时总担心引用问题,如果卸载当时正好有一个线程要访问模块数据就会触发莫名其妙的问题,很多人会在 fini 函数最后加入 sleep(5) 这种调用来模拟一个类似 rcu 的逻辑,然后被经理猛喷,能喷好几年,逢人就跟说谁谁做的这个 sleep(5) 好 low,可经理却一句也不敢喷 tcp waitwait。

paws 作为解决 tcp 序列号区分的通用方案,tcp_tw_reuse 和 tcp_tw_recycle 为 paws 而来,然后 tcp_tw_recycle 又由于和 nat 胶着,为了解决非常稀有的序列号污染问题而引入了一开启就一定会出现的 syn 被默默丢弃的建连失败问题,最终取消了 tcp_tw_recycle,瞎折腾一圈。tcp_tw_recycle 的例子很像为了一盘粗,包了一顿猪肉馅饺子,结果有部分顾客是 msl,还要区分招待,自己给自己找事。

tcp timestamps 不符合高内聚性,它尝试解决很多问题,却每一个问题都解决不好。对于区分新旧连接序列号而言,timestamps 做得太过了,为这种区分根本没必要在连接内递增。

正确的做法是,为 tcp 引入一个 16bit(甚至 12bit,8bit) 的字段,相同四元组连接每新建一次递增 1 就好。松弛一下,四元组 hash 到同一个值的连接共享一个全局字段,每新建一个连接该全局字段递增 1。考虑到一个 host 的建连能力,该全局字段回绕一次的时间大概在 msl 就好了,而这是相对容易的,相当于把 timewait 时间平摊给了每一次连接。

这种方法非常常见,我们每天都在用,我们的分层计时,xx年xx月xx日xx时xx分xx秒,我们的十进制,60 进制计数,再或者我们的空间分层,xx市北大街,xx市东大街。我们可以将高一层的计数称作 “版本号”,以示区分,我们在软件更新,内核协议栈的路由表更新方面(可参考 linux kernel 实现)常用这种方式。相对而言的另一种拙劣方法就是 “等一会儿,等足够久”,让时间遗忘一切。

而 tcp timestamps 的做法是,秒针和分针,时针各自按各自的节奏进步,可想而知会多么混乱,复杂且低效。timestamps 也是要忘掉的,它不是问题的本质,它只是 workaround。本质是什么,本质就是为了区分一个序列号属于哪个连接。

如果一开始 tcp 的 seq 缩短为 16 bit,另外 16bit 作为 version,新旧连接间的序列号就区分出来了,如果觉得同一个连接内部 16bit 不够,那就 24bit,留给连接间 8bit… 总之,32bit 总空间,tcp 全部用于 seq 平坦编码,太粗了,彼时根本没有足以快速回绕的带宽,属过度设计了。

tcp 32bit 序列号空间可容纳 4g 数据,而在 msl 内传输完 4g 数据需要非常大的带宽,在 2010 年以前几乎很难满足这样的条件,即使考虑连接内回绕,最大 4g/4 的窗口约束也足足保证了当时的带宽利用率,tcp 在 1970 年代的考虑过度了,看起来当前的 ipv6 也有类似问题。

如果采用单独的全局 version,以 16bit 全局 ver 为例,连续相邻 65535 次连接才有可能冲突,显然已经超过 msl 了,如果不想占用 32bit 序列号空间就另开辟一个 16bit option 而不必复用 32bit timestampts。检查 paws 时只需要看收到报文携带的 ver 字段与当前连接 ver 是否一致即可。

没了 timewait 状态,很多复杂恼人的逻辑将彻底消失。finwait 收到 fin 并回复 ack 后方可直接关闭,对端 lastack 也不再需要坚持,类似 synack 那帮最多 retry n 次 fin 后亦可直接关闭而无后患。

设计新协议时,不要总觉得 tcp 足够久就是好的,不要什么都学 tcp。

姿势掌握了吗?

浙江温州皮鞋湿,下雨进水不会胖。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/831207.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

4G+北斗太阳能定位终端:一键报警+倾覆报警 双重保障船舶安全

海上作业环境复杂多变,海上航行充满了各种不确定性和风险,安全事故时有发生,因此海上安全与应急响应一直是渔业和海运行业关注的重点。为了提高海上安全保障水平,4G北斗太阳能定位终端应运而生,它集成了一键报警和倾覆…

Edge浏览器新特性深度解析,写作ai免费软件

首先,这篇文章是基于笔尖AI写作进行文章创作的,喜欢的宝子,也可以去体验下,解放双手,上班直接摸鱼~ 按照惯例,先介绍下这款笔尖AI写作,宝子也可以直接下滑跳过看正文~ 笔尖Ai写作:…

Spring MVC系列之异步请求

概述 Spring MVC的本质其实就是一个Servlet。在理解Spring MVC如何支持异步请求之前,需要先知道Servlet3异步如何支持异步请求。参考Servlet系列之Servlet3异步。 Spring MVC对异步请求的支持主要从三个类来看: AsyncWebRequest:requestWe…

【数据结构】:链表的带环问题

🎁个人主页:我们的五年 🔍系列专栏:数据结构 🌷追光的人,终会万丈光芒 前言: 链表的带环问题在链表中是一类比较难的问题,它对我们的思维有一个比较高的要求,但是这一类…

AI大模型探索之路-训练篇10:大语言模型Transformer库-Tokenizer组件实践

系列篇章💥 AI大模型探索之路-训练篇1:大语言模型微调基础认知 AI大模型探索之路-训练篇2:大语言模型预训练基础认知 AI大模型探索之路-训练篇3:大语言模型全景解读 AI大模型探索之路-训练篇4:大语言模型训练数据集概…

DS:顺序表、单链表的相关OJ题训练

欢迎各位来到 Harper.Lee 的学习小世界! 博主主页传送门:Harper.Lee的博客主页 想要一起进步的uu可以来后台找我交流哦! 在DS:单链表的实现 和 DS:顺序表的实现这两篇文章中,我详细介绍了顺序表和单链表的…

使用LinkAI创建AI智能体,并快速接入到微信/企微/公众号/钉钉/飞书

​ LinkAI 作为企业级一站式AI Agent 智能体搭建与接入平台,不仅为用户和客户提供能够快速搭建具备行业知识和个性化设定的 AI 智能体的能力;还基于企业级场景提供丰富的应用接入能力,让智能体不再是“玩具”,而是真正能够落地应用…

C/C++ 字符串与时间戳互相转换

//时间戳转string 1713175204 2024-04-15 18:00:04struct tm *ttime;time_t flag_time time(NULL);ttime localtime(&flag_time);char time_str[100];cout << flag_time <<endl;cout << mktime(ttime) <<endl;sprintf(time_str,"%04d-%02…

PHP的数组练习实验

实 验 目 的 掌握索引和关联数组&#xff0c;以及下标和元素概念&#xff1b; 掌握数组创建、初始化&#xff0c;以及元素添加、删除、修改操作&#xff1b; 掌握foreach作用、语法、执行过程和使用&#xff1b; 能应用数组输出表格和数据。 任务1&#xff1a;使用一维索引数…

uniapp0基础编写安卓原生插件和调用第三方jar包和编写语音播报插件之使用jar包插件

前言 如果你不会编写安卓插件,你可以先看看我之前零基础的文章(uniapp0基础编写安卓原生插件和调用第三方jar包和编写语音播报插件之零基础编写安卓插件), 我们使用第三方包,jar包编写安卓插件 开始 把依赖包,放到某个模块的/libs目录(myTestPlug/libs) 还要到build…

R语言的学习—5—多元数据直观表示

1、数据读取 ## 数据整理 d3.1read.xlsx(adstats.xlsx,d3.1,rowNamesT);d3.1 #读取adstats.xlsx表格d3.1数据 barplot(apply(d3.1,1,mean)) #按行做均值条形图 barplot(apply(d3.1,1,mean),las3) barplot(apply(d3.1,2,mean)) #按列做均值图条形图 barplot(a…

表名不是固定的,django和flask怎样增改删查这个数据表?

在Django和Flask中&#xff0c;操作数据表通常涉及使用ORM&#xff08;对象关系映射&#xff09;或者原生的SQL查询。然而&#xff0c;你提到的sea()函数返回的表名是一个动态生成的字符串&#xff0c;这增加了复杂性&#xff0c;因为ORM通常期望表名是固定的。在这种情况下&am…

C语言数据结构 ---- 单链表实现通讯录

今日备忘录: "折磨我们的往往是想象, 而不是现实." 目录 1. 前言2. 通讯录的功能3. 通讯录的实现思路5. 效果展示6. 完整代码7. 总结 正文开始 1. 前言 顺表实现通讯录: 点击~ 顺序表实现通讯录 在日常生活中&#xff0c;我们经常需要记录和管理大量的联系人信息&…

YOLOv8 是一个相对较新的目标检测算法

YOLOv8 是一个相对较新的目标检测算法&#xff0c;它尚未有官方的代码发布时&#xff08;截至当前知识截止日期&#xff09;&#xff0c;但基于 YOLO 系列的演进和常见的注意力机制&#xff08;如 SE&#xff08;Squeeze-and-Excitation&#xff09;注意力&#xff09;&#xf…

【研发管理】产品经理知识体系-组合管理

导读&#xff1a;新产品开发的组合管理是一个重要的过程&#xff0c;它涉及到对一系列新产品开发项目进行策略性选择、优先级排序、资源分配和监控。这个过程旨在确保企业能够最大化地利用有限的资源&#xff0c;以实现其战略目标。 目录 1、组合管理、五大目标 2、组合管理的…

第74天:漏洞发现-Web框架中间件插件BurpSuite浏览器被动主动探针

目录 思维导图 前置知识 案例一&#xff1a;浏览器插件-辅助&资产&漏洞库-Hack-Tools&Fofa_view&Pentestkit 案例二&#xff1a; BurpSuite 插件-被动&特定扫描-Fiora&Fastjson&Shiro&Log4j 思维导图 前置知识 目标&#xff1a; 1. 用…

c++11开发slam框架的常用技巧

本文以slam开源框架为例列出一些用c++11开发框架的技巧 1 程序框架以及类之间的调用关系处理。 slam由里程计,前端,后端,地图,数据集, 相机 ,建图,匹配,栅格等元素组成,这些元素统统都可以定义为单独的类,每个类之间可以通过智能指针相互指向和调用,每个类定义为接口…

Nacos在微服务架构中如何支持服务发现和注册

在微服务架构日益盛行的今天&#xff0c;服务发现和注册机制成为确保微服务之间高效通信和灵活管理的关键。作为阿里巴巴开源的服务注册与发现、配置管理和服务管理平台&#xff0c;Nacos凭借其简单易用、功能强大和性能卓越的特点&#xff0c;赢得了广大开发者的青睐。本文将详…

渐变色如何做移入效果?

今天&#xff0c;我们ui设计出来的按钮都是渐变色的&#xff0c;移入效果有点烦&#xff0c;记录一下&#xff0c;说实话&#xff0c;就这个移入效果我想了近半小时。 分享一下&#xff0c;慢慢填充颜色的感觉 .button {position: relative;overflow: hidden;z-index: 1;&…

基于springboot实现公司日常考勤系统项目【项目源码+论文说明】

基于springboot实现公司日常考勤系统演示 摘要 目前社会当中主要特征就是对于信息的传播比较快和信息内容的安全问题&#xff0c;原本进行办公的类型都耗费了很多的资源、传播的速度也是相对较慢、准确性不高等许多的不足。这个系统就是运用计算机软件来完成对于企业当中出勤率…