多路径 TCP 调度的另一面

参考前面的文章 一个原教旨的多路径 TCP 和 MP-BBR 公平性推演,一直都破而不立,不能光说怎样不好,还得说说现状情况下,该如何是好。

如果 receiver 乱序重排的能力有限(拜 TCP 所赐),如果非要在多路径上传输 TCP,如果不考虑公平性,单单如何提高吞吐确实难,要找出来原因, 才能彻底解决它,得先分析问题。

设一条 TCP 连接存在两条子路径(subflow):

  • 快路径(Path1):带宽 B1,单向时延 D1;
  • 慢路径(Path2):带宽 B2,单向时延 D2,且 B1 ≥ B2, D1 ≤ D2。

发送策略:

  • 固定间隔 Round-Robin:每间隔 T 时间,轮流在 Path1 和 Path2 上各发送 1 个包;
  • 单快路径(Path1 Only):所有数据仅通过 Path1 发送,间隔 T 时间发送 1 个包。

假设:

  • 所有数据包大小均为 L 字节;
  • 接收端需按序重组数据,乱序包会导致阻塞。

分析 Round-Robin 吞吐量:

  • 发送速率
    • Round-Robin 策略下:
      • 每 2T 时间发送 2 个包,Path1 和 Path2 各 1 个;
      • 平均发送速率: 2 L 2 T = L T \dfrac{2L}{2T}=\dfrac{L}{T} 2T2L=TL
    • 路径带宽限制
      • Path1 的带宽 B1 满足: L T ≤ B 1 \dfrac{L}{T}\le B_1 TLB1
      • Path2 的带宽 B2 需满足: L T ≤ B 2 \dfrac{L}{T}\le B_2 TLB2
      • 由于 B1 ≥ B2,若 L T > B 2 \dfrac{L}{T}\gt B_2 TL>B2,Path2 会丢包,因此最大稳定发送速率需满足: L T ≤ B 2 \dfrac{L}{T}\le B_2 TLB2 T ≥ L B 2 T\ge\dfrac{L}{B_2} TB2L,即 T 不能太小,否则慢路径无法及时传输。
  • 接收端乱序阻塞
    • 数据包到达时间
      • Path1 的包到达时间:D1 + k⋅2T,k 为轮次;
      • Path2 的包到达时间:D2+k⋅2T
    • 乱序条件
      • 若 D2 + k⋅2T > D1 + (k + 1)⋅2T,即 D2 − D1 > 2T,则 Path2 会阻塞 Path1,快路径要等慢路径。
    • 有效吞吐量
      • 由于乱序阻塞,系统吞吐量受限于慢路径的到达速率,慢路径形成漏桶短板;
      • 每 2T 时间可交付 2 个包,但实际受 D2 限制,因此 G o o d p u t R R = 2 L 2 T + m a x ( 0 , D 2 − D 1 − 2 T ) \mathrm{Goodput}_{RR}=\dfrac{2L}{2T+\mathrm{max}(0,D_2-D_1-2T)} GoodputRR=2T+max(0,D2D12T)2L,若 D2−D1>2T,则吞吐量进一步下降。

再分析单快路径的吞吐量:

  • 发送速率:
    • 每 T 时间发送 1 个包,速率 L T ≤ B 1 \dfrac{L}{T}\le B_1 TLB1
  • 无乱序问题,所有包按顺序到达,接收端无需等待。
  • 有效吞吐量: G o o d p u t S i n g l e = L T \mathrm{Goodput}_{Single}=\dfrac{L}{T} GoodputSingle=TL

效率对比的结论非常明确, G o o d p u t S i n g l e ≥ G o o d p u t R R \mathrm{Goodput}_{Single}\ge\mathrm{Goodput_{RR}} GoodputSingleGoodputRR,当且仅当 Path1 与 Path2 效率相同时取等号,两条路径差异越大,吞吐下降越明显,这就是拖后腿。

力气小的经理和力气大的工人一起扛砖头,不如让力气大的自己去扛,两人的协调性成本太大,正与 TCP 乱序重组协调性成本太大一致。怎么办?好办!

让力气小的经理自己去搬他自己的砖,不要和力气大的工人协调。换到 TCP,还是老方法论,横竖一颠倒,转换一个视角,将空洞留在 sender 而不是 receiver。

怕在 receiver 处快路径等慢路径,那就慢路径笨鸟先飞,先到了等快路径即可,落实到具体操作也简单:

  • 在 sender 处,快路径从发送队列头部正序发送,慢路径从发送队列尾部反序发送(最后我再解释为什么),它们处理各自的丢包重传,慢路径直到和快路径 gap 小于阈值 K = f ( R T T ) K=f(\mathrm{RTT}) K=f(RTT)(亦可为一个经验值常量) 后停止发送,推动下一个窗口。

在这里插入图片描述

这很好解释,协调性不一致会付出成本时,解除协调性耦合即可,耦合就会导致木桶效应,各干各的更合适。

直观上理解,如果我们有 4GB 的文件,一快一慢两条路径,快路径依次发送 0,1,2,3,…,慢路径依次发送 4G - 1,4G - 2,4G - 3,…,假设它们在 X 字节处相遇,设快路径平均吞吐为 B,总传输时间将会从 4 G B B \dfrac{4GB}{B} B4GB下降到 X B \dfrac{X}{B} BX

至于 receiver 缓冲区问题,那不是问题,由于已经完全解耦了两个路径的传输,也就成了两个独立的流,各自维护接收缓冲区,最后将它们拼接在一起也行。

另一个问题,看起来以上策略仅对下载大块数据有效,对强调时延稳定性的业务不好使,其实也未必,问题的关键在于业务能容忍多大的 buffer 时延,只要该 buffer 大于多路径最大 BDP,就能应用此方案,只是把上面的 4GB 换成了该 BDP + a。

总之,总要拿个什么来交换成本,以获得收益,越复杂越不划算。举个例子,对于获得肉类的需求而言,驯养食肉动物的转化率远没有食草动物高,因为食肉动物处在食物链更上的生态位,它更复杂,也更不划算,复杂性本身就是成本的组分。

Linux Kernel 自带的 MPTCP 调度算法跟我这个看起来类似,但它没有反着发,而是再慢路径直接发送 s e q = S E Q c u r r + α ⋅ B D P f , 其中 α = R T T s R T T f \mathrm{seq}=\mathrm{SEQ_{curr}}+\alpha\cdot\mathrm{BDP}_f,其中 \alpha=\dfrac{\mathrm{RTT}_{s}}{\mathrm{RTT}_{f}} seq=SEQcurr+αBDPf,其中α=RTTfRTTs,思路依然是让慢路径序列号往后错,但它仍倾向于精确拼接,企图两边正好配合,但这是不可能的,慢路径非常容易与快路径耦合,一旦被快路径赶上,Seq 在快慢路径交错传输和重传,就会引发持续性 HoL 抖动,而这个错开量 α ⋅ B D P f \alpha\cdot\mathrm{BDP}_f αBDPf 由于 RTT 和吞吐率本身的测量误差几乎不可能太准确,也就难怪效果不好了。

之所以倒着发,为了保证慢路径后段一定与快路径解耦(确保后边的数据已经完全准备好),即使 gap 算大了,仅靠快路径自身也能很快接上慢路径已经准备好的数据,而如果 gap 算小了,则影响更小,换句话说,即使抖动也是一瞬间,且快路径主导补洞。

当然,TCP 本身并不支持倒序发送,那这个就不是 TCP 了。既然不是 TCP,索性就多做一点,连 RTT 测量问题也给解了。学学 Swift,到处打标时间戳就很高尚。

其实要更精确地测量两条路径的 RTT 差异非常容易,无论哪条路径收到一份数据需要确认时,将确认报文同时发到多条路径上,sender 只需要比较两个确认报文的时间差,并乘以快路径的吞吐即可获得偏移量,两个问题遗留:

  • 这可能只是反向单向时间戳之差,而正向时间戳更需要,让 receiver 采集数据包时间戳信息并回送回来;
  • 确认报文双发会不好浪费带宽,会,但并不严重,且这是小包加速的典型套路。

既然重新做协议,不要尽抄 TCP 就是了,但要尽量保持简单。

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

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

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

相关文章

大数据学习(92)-spark详解

🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一…

RAG - 五大文档切分策略深度解析

文章目录 切分策略1. 固定大小分割(Fixed-Size Chunking)2. 滑动窗口分割(Sliding Window Chunking)3. 自然语言单元分割(Sentence/Paragraph Segmentation)4. 语义感知分割(Semantic-Aware Seg…

微信小程序引入TDesign组件后报错一直提示路径不对(Component is not found in path)的解决方法

最近在做微信小程序的项目,创建好项目后,按官方方式引入TDesign组件,但还是一直提示报错(Component is not found in path "miniprogram_npm/tdesign-miniprogram/button/button" (using by "pages/login/login&qu…

拦截器和过滤器详解

在 Java Web 开发中,拦截器(Interceptor)和过滤器(Filter)是两种常见的请求处理机制,它们用于对请求和响应进行预处理和后处理 1. 过滤器(Filter) 1.1 作用 Filter 主要用于对 请求…

【机械视觉】C#+VisionPro联合编程———【六、visionPro连接工业相机设备】

【机械视觉】C#VisionPro联合编程———【六、visionPro连接工业相机设备】 目录 【机械视觉】C#VisionPro联合编程———【六、visionPro连接工业相机设备】 前言: 连接步骤说明 一. 硬件连接 支持的相机接口类型: 连接步骤 2. 软件配置 Visio…

笔记:基于环境语义的通感融合技术,将传统通信由“被动接收”转为“主动感知”

《基于计算机视觉的感知通信融合理论与关键技术研发进展》 介绍了联合研发的基于环境语义的通感融合技术研发进展。 观点:利用环境感知信息或环境语义辅助通信的通感融合技术成为6G重要方向之一 产出:基于环境感知的毫米波波束管理方案,并…

Kafka 多线程开发消费者实例

目前,计算机的硬件条件已经大大改善,即使是在普通的笔记本电脑上,多核都已经是标配了,更不用说专业的服务器了。如果跑在强劲服务器机器上的应用程序依然是单线程架构,那实在是有点暴殄天物了。不过,Kafka …

zynq7000 + ucos3 + lwip202_v1_2调试过程

1 现在裸机应用上验证lwip 跑起来可能会报错,看下面的链接解决 zynq 网卡Phy setup error问题 zynq 网卡Phy setup error问题-CSDN博客 2 ping同以后,在zynq上添加ucos系统 链接如下: ZYNQ移植uCOSIII_zynq ucos-CSDN博客 3 移植lwip协议…

Android7 Input(二)Linux 驱动层输入事件管理

概述 在Linux系统中,将键盘,鼠标,触摸屏等这类交互设备交由Linux Input子系统进行管理,Linux Input驱动子系统由于具有良好的和用户空间交互的接口。因此Linux Input驱动子系统,不止于只管理输入类型的设备。也可以将其…

Java内存中的Heap(堆)的作用

Java内存中的Heap(堆)的作用 在 Java 的内存模型中,Heap(堆) 是 JVM(Java Virtual Machine)管理的运行时数据区域之一,主要用于存储程序运行过程中动态分配的对象和数据。它是 Java…

自行车模型与汽车模型的混合策略在自动驾驶中的多维度协同优化

基于动态架构与智能调度的自动驾驶系统设计 #mermaid-svg-1yvF1EzG07ktndY6 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-1yvF1EzG07ktndY6 .error-icon{fill:#552222;}#mermaid-svg-1yvF1EzG07ktndY6 .error-tex…

mysql.8.4.4--初始化报错--libnuma.so.1缺失

错误 mysqld: error while loading shared libraries: libnuma.so.1: cannot open shared object file: No such file or directory解决办法:下载相关依赖 sudo apt update sudo apt install numactl然后重新初始化 mysqld --initialize

【区块链安全 | 第三篇】主流公链以太坊运行机制

文章目录 1. 以太坊账户类型2. 以太坊网络架构2.1 节点类型2.2 交易流程 3. 共识机制4. Gas 机制4.1 Gas 计算方式4.2 以太坊 EIP-1559 交易机制 5. EVM(以太坊虚拟机)5.1 EVM 结构5.2 EVM 指令5.3 EVM 运行机制 6. 智能合约7. ERC 代币标准7.1 ERC-207.…

计算机三级信息安全部分英文缩写

eip,指令寄存器,用于存放指向下一条将执行指令的指针,即返回地址栈顶指针esp基址指针寄存器EBP,基地址数据执行保护DEP(Data Execute Prevention)技术可以设置内存堆栈区的代码为不可执行状态,从而防范溢出后代码的执行…

【Goalng】第九弹-----文件操作、JSON处理

🎁个人主页:星云爱编程 🔍所属专栏:【Go】 🎉欢迎大家点赞👍评论📝收藏⭐文章 长风破浪会有时,直挂云帆济沧海 目录 1.文件操作 1.1文件介绍 1.2.文件流 1.3.打开和关闭文件 1…

C#高级:启动、中止一个指定路径的exe程序

一、启动一个exe class Program {static void Main(string[] args){string exePath "D:\测试\Test.exe";// 修改为你要运行的exe路径StartProcess(exePath);}private static bool StartProcess(string exePath){// 创建一个 ProcessStartInfo 对象来配置进程启动参…

猜猜我用的是哪个大模型?我的世界游戏界面简单的模拟效果

我的罗里吧嗦的,根据小朋友的要求,边听边写边输入的提示词: 请生成一段完整的在网页中用html5和javascript代码模拟“我的世界”中游戏场景的互动画面,要求提供若干人物选项可以选择,请自行选择需要使用哪些库或框架来…

AI知识补全(八):多模态大模型是什么?

名人说:人生如逆旅,我亦是行人。 ——苏轼《临江仙送钱穆父》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 上一篇:AI知识补全(七):AI Agent 智能…

更新docker 容器时,提前换后端jar 包,为什么会存在异常

我们现场更新时,通常都是提前将后端jar 包替换了,然后到了更新的时间,只需要更新相关的前端文件和修改各种配置,就行了。 但是最近一次更新操作中,忽然发现,提前更新后端包,会存在依赖丢失问题…

LoRA 模型微调框架核心原理及实现步骤

LoRA(Low-Rank Adaptation)模型微调框架通过低秩矩阵分解原理,实现了对大型预训练模型的高效微调。其核心原理是:在冻结预训练模型权重的基础上,向特定层注入可训练的低秩矩阵,以极少量参数(通常…