滑动窗口停等与多路径乱序传输天然不容。
多路径传输,每条路径对数据的接收是平等的,因此乱序是自然的,如果 receiver 从某条路径收到了不连续数据,回sack 吗?如果不回,回什么?如果回,sender 会频繁误解,切换拥塞状态机。
而 mptcp 则将简单问题复杂化了,它明显是把一条 flow 拆分成了多条 subflow,每一条 subflow 依然会有同样问题,规模小些罢了。
同样的,flowlet 方案也是小改,算是时间版本的 mptcp,在一个相对大但又足够小的时间窗口中乱序传输,保证 receiver 按序接收,和 mptcp 一样,依然还是没有摆脱 flow 的本质。
原罪在于 tcp 一开始那个基于停等的滑动窗口,它产生了积累确认,而积累确认必须要求保序,这就是 flow 的起源。但在多路径传输时,保序到达才最不自然,它只是诸多种数据到达方式排列组合中的一种,并不特殊,这得多小的概率啊。
去掉积累确认,完全 sack 就是了,多路径 nak 可能更复杂,因为这条路径的 hole,可能被别的路径补了。sack 反而可以各自顾各自,因为除非报文被复制,否则不会收到多次。
再说数据的交付接收。
流式接收同样不自然,即便流式应用,其流语义也只有应用本身最了解,组装及丢弃工作应由应用本身负责,而不是传输层无条件流式交付。
这也许因为在 tcp 初始时期只有块文件传输和远程登录传输两种流式应用,而原罪则是 bsd socket 接口,直到现在 rcv 接口依然是一小块一小块接收,socket 下面几乎只有 tcp 和 udp(不抬杠,肯定有别的,但都很别扭,特别对于多路径逻辑,非常不好用)。自然的方式应该像 rdma 那样,而内存倒也未必必须连续,重组工作解耦给 cpu 即可,执行一个插入(目前 ofo 队列就是这样管理),传输层本身不必操心。
“套接” 实际上是英文单词 “socket” 的直接翻译,它是指将两个东西联结在一起的过程,一般描述的是针对某种物体或设备而言。进程间通信其实没有必要抽象到如此地步。我们知道,分组交换的数据报通信需要先将数据报装进 “箱子”,再将箱子放进 “管子” 里,套接字直接抽象到了管子层次,也就不在乎放进管子里的是箱子还是散货了。事实上,只要抽象到箱子就够了,甚至散货本身(rdma 即是如此),这样多路径乱序传输就是自然而然的了。
但现实不似你所愿,即使端到端协议支持多路径乱序,ip 路由也难支持,大概率所有这些 “逻辑多路径” 会被ip路由收敛到现实中同一条路径,经历相同的拥塞。ecmp 也解决不了问题而只能缓解。
说了这么多,还是老话重复,应用的流抽象不必在传输中被保证,参见 现代操作系统和 TCP/IP(第二篇) 以及 mapreduce 逻辑。不自然的逻辑在我们看来竟然如此自然,因为一开始 tcp/ip 选择了不自然的方式,而这一切竟然都是历史(电路交换)的包袱。
这是一则在路上发的朋友圈,但有点长了,写成一篇文字吧。文章来源:https://www.toymoban.com/news/detail-463312.html
浙江温州皮鞋湿,下雨进水不会胖。文章来源地址https://www.toymoban.com/news/detail-463312.html
到了这里,关于TCP 滑动窗口停等与多路径传输的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!