scale up 不能优化 TCP 聚合性能

news2025/6/5 0:59:47

scale up 作为一种系统扩展优化的方法,旨在提高系统组件的执行效率,比如替换更高性能的硬件或算法。是否可以此为依据优化 TCP 呢,例如通过多条路径聚合带宽实现吞吐优化(对,还是那个 MPTCP),答案是否定的。

因为 TCP 是 scale out 协议,绝大多数情况下,你无法在不触碰另一个瓶颈的前提下,通过更多资源换得等价的性能。

没有任何 scale up 是线性的,都会受边际效用和沟通成本影响而趋平,但为便于理解,我将 scale up 系统的单流性能 y 随资源 x 变化写作 y = a · x,而在 scale out 系统则为 y’ = b,其中 a,b 为常量。举个例子,网卡作为 x 升级后突破了原始瓶颈,y 变大,b 产生新值,此时增加多块同样的网卡,无论怎么做也不会将更多的网卡利用起来让单个 y’ 从新 b 继续提升,那么产生该单流的协议就是一个 scale out 协议。

要理解传输性能优化,首先得区分带宽和吞吐,忽略丢包,重传,延时抖动等因素,它们到底在衡量什么。

如下图形象,带宽是一个静态空间中的概念,衡量管道截面积,如果多根管道组成传输路径(即多路径传输),就是它们截面积之和,而吞吐是一个动态时间序中的概念,衡量单位时间首尾流入管道的数据量和流出管道的数据量之差。
在这里插入图片描述

简单解释一下吞吐的描述。虽然管道可以提供 RTT_Normalized · (S1 + S2) 的带宽,但如果某时刻从左边注入这么多数据,RTT_Normalized 过后,仅流出 RTT_Normalized · |RTT2 - RTT1|/RTT2 · (S1 + S2) 数据,若要流出更多的数据,则必须在更大 RTT2 路径上更早注入数据,如果没有足够的数据提前注入,就要在右侧等待重组,该力度由 α 调节,表现为多路径调度和重组算法,由这些算法决定(前面写过,但不是本文重点),对于可靠传输,左边不等右边等,怎么优化都没用。

上述式子表明,路径 RTT 越异构,越聚合越差,类似健康人拖着一个瘸子走。

从要解决的问题而不是概念入手,带宽优化是一个 scale out 扩展问题,只要你多聚合一个管道,里面跑数据,截面积肯定能增加,而吞吐优化则是 scale up 扩展问题,需要依赖并联合重传,调度,乱序重排序等算法单元。这个理解可让你一下子就能区分诸多传输协议的聚合处理,哪些是好的,哪些是坏的。

在低速场景,TCP 各项指标都不孬,它的边际收益随资源的增值曲线上凸远没到值得警惕的地步,很难看出 TCP 更善于填充带宽还是优化吞吐,但 TCP 是典型 scale out 协议,特别当它被喂到 10Gbps+ 后,单流吞吐就显得力不从心,边际收益曲线几乎水平甚至向下减损,只能靠注入多流横向填充带宽。

早在 2010 年代初,随着带宽持续提高和低延时需求激增,依靠统计均值回归的 TCP 带宽利用率问题就开始突出,TCP 不得不靠填充更多 buffer 的代价来填充更多带宽,BBR 正是在 2016 年底放出缓解这一问题,然而更严峻的挑战在数据中心,在数据中心网络 scale up 扩展中,高性能网络中的 TCP 传输过程,总有某些资源利用率不足,只能 scale out 去填充,紧接着就会遭遇另一些资源过载,于是继续 scale up,再 scale out,针对 TCP scale out 的资源密度内卷问题,各类适应 scale up 扩展的协议纷纷亮相,SRD,Homa,Falcon,TTPoE,对于应对资源密度问题,这些都是正确的。

从文初的定义看,只要可以通过将数据乱序 spray 到更多网卡,就可以压缩单卡串行时间,从而提高 y’。

但有两条几乎同时但完全走错的路,DPDK 用户态 TCP 协议栈和 MPTCP。这两条错误本质上都是在用 scale up 思想扩展 scale out 协议,相当于给鱼带游泳圈。

TCP 的串行本质注定了它的处理逻辑中总在同步,总在等待。TCP 无法享用可并行分发的 scale up 设施,这是它作为 scale out 协议的根源,作为相对一面,数据中心的很多其它协议往往对并行资源的利用率更高,同时将串行流抽象解耦到另一些可 scale up 的设施中来保证,依靠重排序解决,从而跳出了资源密度的内卷。我并非说 Homa 是最好的替代,但它的宣讲中对 TCP 的总结最为全面:It’s Time to Replace TCP in the Datacenter。

网络传输时间尺度即使在数据中心都比主机时间尺度大至少一个数量级(10us vs. 800ns),在用户态协议栈中,CPU 将大量时间浪费在 TCP 主机时间同步对齐网络时间,为了比内核 TCP 更快,这个能耗代价着实大。主机侧对 TCP 单流效率无法通过更多的资源 scale up,传输侧的 MPTCP 又进一步加深了时间尺度的鸿沟。

MPTCP 池化了带宽,但却没有改变 TCP 的流式抽象,正如用户态 TCP 协议栈内存不等 CPU 等一样,MPTCP 是带宽不等内存等,串行过程是个漏桶模型,由最慢的一环决定,谁快谁等。比如说 MPTCP socket 接口,先忽略路径拥塞和滑动窗口,假设它们都不受限,在一个单线程中 spray 一条串行流一个窗口的数据,根据 Little 定律,系统总容量没有任何改变。多 Subflow 间的任何抖动,都会把时延单调叠加到内存中的重排序等待,RTT 越异构越发散,而我上周的文章证明,MPTCP 多路径间的抖动发散而不收敛,在统计意义上,相比标准 TCP,MPTCP 的低时延体验趋向劣化:
在这里插入图片描述

若考虑路径拥塞和滑动窗口,是单路径拥塞控制更简单还是并行化调度一条串行流叠加多路径耦合拥塞控制更简单,搞定了拥塞控制,你又如何保证拥有足够的,多个窗口的数据供 MPTCP 调度。

多路径显然在 MPTCP 这里用错了,因为 MPTCP 本意想叠加吞吐,这是个 scale up 扩展,TCP 无能为力。

作为串行流的 MPTCP,时间序约束着序列号,而序列号又让时延单调发散,解除二者的关联才是多路径传输的正确姿势,那些数据中心多路径传输协议,几乎都可在多路径随意乱序分发消息,而乱序意味着不可靠,因为没有任何端到端机制能区分乱序和丢包,丢包对重传的依赖也解除了,若要支持可靠传输,协议必须单独处理,比如通过 NACK,Request 而不是类似 TCP 带内积累确认。

多路径传输将带宽资源池化,这是典型的 scale up 思想,类似为主机升级更多核的 CPU,但更多核的 CPU 也无法优化一个单线程程序,除非将它重写成可并发执行的多线程代码,但有些逻辑本就发生在时间序本身,无法 scale up,比如处理一个 TCP 流。若作者理解了这个,就不会出现用户态 TCP 协议栈和 MPTCP 这些东西。

另一方面,也就理解了 TCP 协议处理的两面,要么强大的 CPU(和网卡) 造成网络拥塞,要么强大的网络造成 CPU 过载,却无法刚刚好,也无法优化某个单独的方面。因为 TCP 协议处理时间序本身,而时间序无法横向跨越资源,就会遭遇资源密度问题,在资源不足的 stage 过载,在资源充足的 stage 造成低利用率,这就是 TCP 无法适应高性能网络的根源。

再说到单流 TCP 处理本身,涉及到另一个系统如何组织调度任务的问题,是 run-to-complete 还是 pipeline,在此视角,我会继续分析 MPTCP,导出与其它视角相同的结论,即 MPTCP 不行。

处理一个串行流,直观理解肯定是 run-to-complete 最快,但事情没这么简单。 浅引我几年前的两篇文章:加密一条保序流,大吞吐的不二法门。

但还是转贴文中两个图,左边是 scale up 扩展,右边是 scale out 扩展:
在这里插入图片描述

一个并行加密逻辑切断了 run-to-complete 过程,插入了 lock-wait-unlock 的重排序逻辑。

这里的原则是,当串行操作的时间尺度大于重排序时间尺度时,并行化它就值得。加密一条串行流,设加密过程耗时为常量 T1,流长为 n,加密核大于 n,串行加密时间复杂度为 O(n),而如图所示并行加密重排序时间取决于最久的加密时间,时间复杂度为 O(1),何乐而不为。

现在以此原则再审视 MPTCP,设多路径时延为相同常量 T2,流长为 n,路径数量为 m,串行单路径传输时间复杂度为 O(n),对于 MPTCP 而言,传输阶段时间复杂度为 O(n/m),合并阶段为 O(n log m),总体上 O(n/m + n log m) ≈ O(n log m) > O(n)。

这意味着,要么抛弃 MPTCP,要么只分 2 条 Subflow,m 越大越差。相比较而言,标准 TCP 则是准排序的,面对偶尔的,罕见的乱序,也只是执行一个 O(log n) 的插入操作,即 O(log n) < O(n log m)[m = 2] < O(n log n)。

必须要注意的是上述时间复杂度推导存在的偏见,时间复杂度只表示时间随规模增长的趋势曲线形状,它绝不表示程序执行的绝对时间,在加密一条串行流的推导中,我视加密一个单位数据时间为常量 T1,在传输一个串行流时对应的时间常量是 T2,T1 我取了最长时间作为 O(1) 中 1 的常量根据,T2 我却忽略了。

试想在一个 RTT 为 T2 = 500ms 的路径传输,窗口大小为 w,一窗数据传输时间 500ms,m 路并行传输 m 个窗口的时间上界为 (500 + log (n/w))ms,小于串行传输所需的 (n/w) · 500ms,几乎可以肯定,节省下来的时间 ((n/w) · 500 - 500 + log (n/w))ms 小于主机排序时间 β · (n/w) · log m,其中 β 为主机时间尺度。因此,当路径 RTT 足够大时,MPTCP 分担多个窗口的数据传输依然有收益,这里的问题在于是否有足够的 “多个窗口的数据”,还是回到了老问题,大部分情况下你只有一个窗口的数据,难点在于如何在多路径 spray 一个窗口的数据仍有收益,这还是调度策略的问题,这才是难点,分析过了,不再赘述。

那些支持乱序传输的可靠协议为什么没有这个时间复杂度的问题?理论上它们重排序的成本并不会比 MPTCP 更少,答案在于上面段落里一句话,它们将 “串行流抽象解耦到另一些可 scale up 的设施中来保证”,它们可能没有滑动窗口,它们可能直接传递包含位置和空洞信息的接收 buffer 状态位图,而这些均可以通过 scale up 优化甚至并行化,它们不像 TCP,从 socket 到 socket,始终就是那一条串行流,MPTCP 重排序步骤真的就是在做一道单线程归并排序面试题。

这可如何解释各级别会议论文,公众号展示的各大卷厂的 MPTCP 卷果,如何解释各类吊打内核 TCP,吞吐提升 好几十% 的诳语:

  • 他们的仿真环境是他们的仿真环境;
  • 测试环境 RTT 异构性弱,真实环境更不可控;
  • m 不大,O 常量主导,软硬件加速机制与内核 TCP 相比占优;
  • 相比内核 TCP 代价高昂,无论 CPU 成本还是卷客们的工资成本;

有以下真实环境进行测试比对多流标准 TCP 对带宽,吞吐的 scale out 和 MPTCP 对带宽,吞吐的 scale up。

客户端为普通 PC,服务器为云主机,有 3 条路径连通,其中 1 条 5G,20Mbps,30ms,一条有线宽带,50Mbps,20ms,1 条 4G,约 5Mbps,35ms:
在这里插入图片描述

只说多流标准 TCP 如何做。

先吐个陈年老槽。详见 Linux策略路由和iptables OUTPUT链的一个细节,简单说一下。

要想在 5G,4G,宽带路径之间负载均衡 TCP 流,需要配置策略路由(ip-rule),同时需要为分配到该路径上的 TCP 数据包选择对应该路径网卡的 IPv4 地址,可是 Linux 内核不支持为一个路由项多次修改源 IP:

  • 即使将 dummy 网卡地址清掉,并设置 default 指向 dummy,系统依然会为数据包选择一个不适配的 saddr;
  • 必须配置 nat MASQUERADE 重新指定 saddr;

其根源在于,iptables OUTPUT 在路由之后,而路由子系统并不知道 iptables mangle rule 会在路由之后 mark 数据包,所以它必须为数据包指定好 saddr,问题在于,当 Linux 内核发现数据包的 daddr,fwmark 等信息发生改变后,其 nf_reroute 逻辑不支持 saddr 的重新选择,这一点至今(v6.15)依然未改变。

给出配置:

# iptables 配置
*nat
-A POSTROUTING -j MASQUERADE
*mangle
-A OUTPUT -j CONNMARK --restore-mark
-A OUTPUT -m mark ! --mark 0x0 -j ACCEPT
-A OUTPUT -p tcp --dport 5201 -m statistic --mode random --probability 0.5 -j MARK --set-xmark 100
-A OUTPUT -m mark ! --mark 0 -j CONNMARK --save-mark
-A OUTPUT -m mark ! --mark 0 -j ACCEPT
-A OUTPUT -p tcp --dport 5201 -m statistic --mode random --probability 0.25 -j MARK --set-xmark 200
-A OUTPUT -m mark ! --mark 0 -j CONNMARK --save-mark
-A OUTPUT -m mark ! --mark 0 -j ACCEPT
-A OUTPUT -p tcp --dport 5201 -m statistic --mode random --probability 0.25 -j MARK --set-xmark 300
-A OUTPUT -m mark ! --mark 0 -j CONNMARK --save-mark
-A OUTPUT -m mark ! --mark 0 -j ACCEPT
-A OUTPUT -p tcp --dport 5201 -j MARK --set-xmark 100
-A OUTPUT -j CONNMARK --save-mark
-A OUTPUT -j ACCEPT

# ip-rule 配置
32763:  from all fwmark 300 lookup lb42
32764:  from all fwmark 200 lookup lb41
32765:  from all fwmark 100 lookup lb50

# policy-routing 配置(每张表分别指向默认网关,略)

总吞吐稳稳当当 70Mbps+,至于哪个线程被扔进低带宽,高延时路径,纯属运气不好,但在统计意义上,好坏运气机会均等。同样聚合 3 条路径的带宽,MPTCP 可聚合吞吐吗?

结论是,多流标准 TCP 填满了带宽,聚合了总吞吐,但未对单独的流承诺吞吐,MPTCP 既没有填满带宽,更奢谈承诺吞吐,实话实说,总吞吐只有 25~40Mbps,很容易理解这个结果,路径太异构了。

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

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

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

相关文章

Python-matplotlib库之核心对象

matplotlib库之核心对象 FigureFigure作用Figure常用属性Figure常用方法Figure对象的创建隐式创建(通过 pyplot)显式创建使用subplots()一次性创建 Figure 和 Axes Axes(绘图区)Axes创建方式Axes基本绘图功能Axes绘图的常用参数Ax…

Linux 脚本文件编辑(vim)

1. 用户级配置文件(~/.bashrc) vim ~/.bashrc # 编辑 source ~/.bashrc # 让编辑生效 ~/.bashrc 文件是 Bash Shell 的配置文件,用于定义用户登录时的环境变量、别名、函数等设置。当你修改了 ~/.bashrc 文件后,通常需要重新…

学习BI---基本操作---数据集操作

什么是数据集, 数据集(Dataset)​​ 是指从原始数据源(如数据库、Excel、API等)提取并经过标准化处理后的数据集合,通常以二维表形式存储,用于支撑报表、仪表盘等可视化分析。 数据集在QuickB…

初学大模型部署以及案例应用(windows+wsl+dify+mysql+Ollama+Xinference)

大模型部署以及案例应用(windowswsldifymysqlOllamaXinference) 1.wsl 安装①安装wsl②测试以及更新③安装Ubuntu系统查看系统以及版本安装Ubuntu系统进入Ubuntu系统 2、docker安装①下载安装包②安装③docker配置 3、安装dify①下载dify②安装③生成.en…

Redis部署架构详解:原理、场景与最佳实践

Redis部署架构详解:原理、场景与最佳实践 Redis作为一种高性能的内存数据库,在现代应用架构中扮演着至关重要的角色。随着业务规模的扩大和系统复杂度的提升,选择合适的Redis部署架构变得尤为重要。本文将详细介绍Redis的各种部署架构模式&a…

C++哈希表:unordered系列容器详解

本节目标 1.unordered系列关联式容器 2.底层结构 3.模拟实现 4.哈希的应用 5.海量数据处理面试题 unordered系列关联式容器 在c98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时效率可以达到logN,即最差的情况下需要比较红…

WordPress通过简码插入bilibili视频

发布于:Eucalyptus-Blog 一、前言 B站是国内非常受欢迎的视频分享平台,上面不仅内容丰富,而且很多视频制作精良、趣味十足。很多人,比如我,就喜欢将B站的视频通过 iframe 嵌入到自己的网页中,但这段代码又…

ZLG ZCANPro,ECU刷新,bug分享

文章目录 摘要 📋问题的起因bug分享 ✨思考&反思 🤔摘要 📋 ZCANPro想必大家都不陌生,买ZLG的CAN卡,必须要用的上位机软件。在汽车行业中,有ECU软件升级的需求,通常都通过UDS协议实现程序的更新,满足UDS升级的上位机要么自己开发,要么用CANoe或者VFlash,最近…

黑马k8s(十七)

一:高级存储 1.高级存储-pv和pvc介绍 2.高级存储-pv 3.高级存储-pvc 最后一个改成5gi pvc3是没有来绑定成功的 pv3没有绑定 删除pod、和pvc,观察状态: 4.高级存储-pc和pvc的生命周期 二:配置存储 1.配置存储-ConfigMap 2.配…

掌握HttpClient技术:从基础到实战(Apache)

目录 前言 一、Apache HttpClient简介 二、HttpClient基础使用 1. 添加依赖 2. 创建HttpClient实例 3. 发送GET请求 4. 发送POST请求 三、HttpClient高级配置与实战案例 1. 连接池优化 2. 超时与重试配置 3. 文件上传(Multipart) 总结 前言 …

sql知识梳理(超全,超详细,自用)

目录 通识 查询的基本语法 数据库(database)操作 表(table)的操作 表中列的操作 索引操作 表中行的操作 insert into语句 update语句 删除语句 select语句 表与表之间的关系 连接查询 子查询 视图 数据备份与还原 …

[ Qt ] | QPushButton常见用法

目录 绑定键盘快捷键 前面已经说了很多用法了,下面主要说说绑定键盘,设置Icon图片。 绑定键盘快捷键 实现四个按钮,可以使用wsad来控制另一个按钮的上下左右的移动。 #include "widget.h" #include "ui_widget.h"Wid…

电脑驱动程序更新工具, 3DP Chip 中文绿色版,一键更新驱动!

介绍 3DP Chip 是一款免费的驱动程序更新工具,可以帮助用户快速、方便地识别和更新计算机硬件驱动程序。 驱动程序更新工具下载 https://pan.quark.cn/s/98895d47f57c 软件截图 软件特点 简单易用:用户界面简洁明了,操作方便,…

【机器学习基础】机器学习入门核心:数学基础与Python科学计算库

机器学习入门核心:数学基础与Python科学计算库 一、核心数学基础回顾1. 函数与导数2. Taylor公式3. 概率论基础4. 统计量5. 重要定理6. 最大似然估计(MLE)7. 线性代数 二、Python科学计算库精要1. NumPy:数值计算核心2. SciPy&…

上交具身机器人的视觉运动导航!HTSCN:融合空间记忆与语义推理认知的导航策略

作者:Qiming Liu 1 ^{1} 1, Guangzhan Wang 2 ^{2} 2, Zhe Liu 3 , 4 ^{3,4} 3,4 and Hesheng Wang 1 , 3 , 5 , 6 ^{1,3,5,6} 1,3,5,6单位: 1 ^{1} 1上海交通大学自动化系, 2 ^{2} 2上海交通大学软件学院, 3 ^{3} 3上海交通大学教…

【C++并发编程01】初识C++并发编程

1、并发是什么 并发是指两个或更多独立的活动同时发生,现实生活中常见的并发场景如边吃饭边看手机。 1.1、计算机中的并发: 计算机领域的并发是指在单个系统里同时执行多个独立的任务,而非顺序的进行一些活动。 我们在电脑上能够边听音乐边和…

Mysql库的操作和表的操作

Mysql库和表的操作 库的操作1.查看数据库列表2.创建数据库3.使用数据库4.查看当前在那个数据库中5.显示数据库的创建语句6.修改数据库7.删除数据库8.备份和恢复数据库9.查看数据的连接情况(简单来说就是查看有多少人使用你的数据库) 表的操作1.创建表2.查看表结构3.修改表本身(…

LangChain-结合GLM+SQL+函数调用实现数据库查询(三)

针对 LangChain-结合GLM+SQL+函数调用实现数据库查询(二)-CSDN博客 进一步简化 通过 LangChain 和大语言模型(GLM-4)实现了一个 AI 代理,能够根据自然语言提问自动生成 SQL 查询语句,并连接 MySQL 数据库执行查询,最终返回结果。 整个流程如下: 用户提问 → AI 生成 SQ…

抖音商城抓包 分析

声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 抓包展示 总结 1.出于安全考虑,本章未…

性能优化 - 案例篇:数据一致性

文章目录 Pre引言1. 分布式缓存概念2. Redis 与 Memcached 区别概览3. Spring Boot 中使用 Redis3.1 引入依赖与常用客户端3.2 RedisTemplate 的基本用法3.3 Spring Cache 注解式缓存 4. 秒杀业务简介及挑战5. Lua 脚本实现原子库存扣减5.1 准备阶段:数据预加载5.2 …