TCP还是UDP:加速场景下的取舍逻辑

list 文章目录

TCP和UDP的对比一般被简化为一句话:TCP可靠,UDP不可靠。

单看协议本身,这个说法站得住,却把工程上最关键的一点藏了起来:’可靠‘和’不可靠‘不是优劣之分,而是两条不同的取舍路径。TCP 选了可靠性,账单是排队与等待;UDP 把可靠性让出去,换来自主权与响应速度。做加速时二者分道扬镳:针对 TCP 的优化,主要是在替它消化可靠性带来的时延;针对 UDP 的优化,则是在’不承诺送达‘的前提下有选择地弥补丢包。

两边的加速手段不能混用:把TCP那套逻辑搬到UDP上会伤即时性,把UDP那套搬到TCP上又解决不了窗口增长受限的问题。

TCP的代价:顺序交付与队头阻塞

TCP向应用层提供一个保证:数据按发出顺序到达,不丢、不重、不乱。为了维持这个保证,TCP在协议栈内部做了几件事。

接收侧会维护一个重排序缓冲区。在 IP 网络中乱序极为常见,因为不同包完全可以走不同路径;一旦到达顺序与发送顺序不符,接收端就必须先把缺失的那个包等回来,才能把后续数据交付给应用。这就是队头阻塞(Head-of-Line Blocking):一个包没到,后面所有已经收到的包都被一起扣住。

这条链路越慢,队头阻塞越难消化。取 RTT 等于 200ms 的情形:丢了一个包,接收端至少得等 200ms 才能见到重传,而这段时间里陆续抵达的数据全被缓冲区压着。应用层看到的画面不是’200ms 之后逐步恢复‘,而是’先静默 200ms,紧接着数据一拥而入‘。网页加载时的表现是某个资源卡住后突然完成;实时类应用则完全受不了——200ms 之前的游戏状态早已过期。

TCP 的另一笔开销来自拥塞控制的保守性格。慢启动时窗口指数式膨胀看似很快,可一旦逼近链路容量,基于丢包的算法会主动制造丢包去试探天花板,随后削减窗口重新爬坡。短 RTT 链路上这套循环很迅速;到了长 RTT 链路,每一次丢包都要多个 RTT 才能重新回到满速。

加速器如何介入TCP

TCP加速器的核心逻辑是:把TCP的代价隔离在短RTT段内。

加速器把端到端的一条 TCP 切成两截后,每一截的 RTT 都会显著下降——用户到加速节点这一段,常常只有直连时的 1/3 到 1/4。队头阻塞依旧会出现,但它持续的时间与 RTT 成正比,RTT 越短,解开得越快。窗口恢复也随之提速:在 200ms RTT 上需要 2 秒才能爬完的窗口恢复过程,在 50ms RTT 上 0.5 秒即可走完。

拆分也带来一个新麻烦:两段 TCP 互不知情,各自的拥塞控制互不通气。用户到节点这一段可能很宽裕,窗口一路冲高;节点到目标这一段却在排队,窗口被牢牢压住。数据于是高速灌入节点,堆积在它的发送缓冲区里。只要堆积量超过’节点至目标‘链路的带宽延迟积,多余的排队时延就在加速器内部被凭空制造出来。

这意味着,加速器的有效运作要求接入点的缓冲区管理选路策略与两段链路的可用带宽差异匹配。若入口链路远快于出网口链路(比如用户是千兆宽带,出网口链路由于跨洋而只有几十Mbps的有效吞吐量),接入点必须主动向用户端施加反压——通过调整TCP窗口或时延ACK来降低入口段的发出速率。不做这个调优的加速器,会在接入点内部制造自己的拥堵点。

所谓稳定,是节点会自己换。狗急加速器把选路做成持续动作,每条专线的时延、抖动、丢包都在评估范围内,最优解变了就立刻跟着变。

UDP的设计:不保证,不阻塞

UDP向应用层提供的是一个完全不同的契约:数据报尽力交付,不保证到达,不保证顺序。若数据报丢失,UDP不补发。若数据报乱序,UDP不重排。应用层收到什么就是什么,UDP不替应用做任何决定。

正是这种’把决定权留给应用‘的设计思路,让大量实时应用站到了 UDP 这边。游戏、VoIP、实时视频这一类,对’及时‘的要求高于对’完整‘的要求:语音包丢了,宁可听一小段静音,也不愿等 200ms 之后把早已过时的音频插回当前时刻;位置更新丢了一包也没大碍,只要频率够密,下一个包在几毫秒内就会把它覆盖掉。

UDP把可靠性决策权交给了应用层。应用能够自己实现选择性补发(只补发关键报文),能够实现FEC(用冗余换丢包恢复),也能够什么都不做(容忍丢包)。这种灵活性是UDP在即时场景中的核心价值。

但UDP在公网上有一个结构性的劣势:网络中间设备对它的态度。

一旦链路开始拥塞,路由器的队列管理策略通常是偏袒 TCP 的。以 WRED 为代表的主动队列管理算法会有选择地丢 UDP 包,理由很简单:UDP 不会像 TCP 那样根据拥塞信号降低速率。于是一条不减速的 UDP 流在拥堵链路上被视为’不合作的流量‘,优先被标记或丢弃。这就是网络高峰时段 UDP 丢包率常高于 TCP 的原因——并非 UDP 天生更脆弱,而是设备策略在设计上就去保护 TCP 的公平性。

加速器对UDP能做什么

加速器的路由选择

UDP加速不必须拆分接入,由于UDP没有接入。UDP加速不必须管理拥堵窗口,由于UDP没有窗口。那么加速器在做什么?

通路选择仍然是第一位的。若加速器能将UDP报文从一条丢包率2%的公共通路迁移到一条丢包率0.2%的私有骨干网通路,提速成效直接体现在应用层的丢包减少上。这部分逻辑和TCP加速相同,但对UDP的收益往往更看得出来——由于UDP对丢包没有自愈能力,丢一个就是一个。

在这条更优的通路之上,加速器能够在两端接入点之间增加FEC。发出端在连续N个报文后附加M个冗余包,使得接收端在N+M个包中任意丢失不超过M个时都能完整恢复。FEC不消除丢包——物理链路上的报文仍然在丢失——但它让应用层感知到的丢包率降到零。

FEC 的账单由两部分构成:额外的带宽占用,以及编码带来的时延。发送端必须攒够一定数量的数据包才能生成冗余包——对每秒 60 个更新包的游戏流量来说影响不大(攒 4 个包约需 67ms),低频流量却可能要等上更长时间。这段积累时间加上编码运算本身的耗时,就是加速器额外引入的处理延迟。

不用挨个试着点节点。狗急加速器按照实时链路质量给专线排序,判断在毫秒级完成,接通时已经是当下最合适的那一条。

在工程实践中,经常观察到一个权衡:开启FEC后,游戏内显示的丢包率走低,但基础ping值增加了3-5ms。对大多数玩家来说,丢包率从1%降到0带来的体验好转远大于ping值增加5ms的代价。但对于对时延极度敏感的场景(比如职业电竞),这个权衡必须被明确意识到。

误判:QUIC与”UDP加速”

QUIC是一个基于UDP的传输协议,它在应用层实现了类似TCP的可靠传输和拥堵控制。很多加速服务声称支持”UDP加速”,但实际测试会发现它们对QUIC的处理并不一致。

一些加速器将QUIC传输量当作普通UDP处理——单纯转发,不做FEC,不做通路调优。这是合理的,由于QUIC已经内置了拥堵控制和丢包恢复,外部的FEC有可能干扰QUIC自身的速率调节逻辑。但若加速器对QUIC什么都不做,用户看到的效果就和直连没有区别(除了通路有可能不同)。

另一些加速器会尝试对QUIC传输量也做TCP式的分段中继——终结QUIC接入,在内部用自定义协议传输,到出网口接入点再重建QUIC接入。这种做法等于破坏了QUIC的整程加密和认证模型,一般必须客户端安装根证书才能中间人解密。对用户来说,带来的安全风险有可能超过加速收益。

一个更容易混淆的情况是,加速器宣称”UDP加速”,但实际只调优了特定端口的UDP传输量(比如常见的游戏端口),而对QUIC采用的443端口的UDP传输量走的是另一套逻辑(甚至有可能被降级为直连)。用户在跑一次测速时看到UDP加速有效,但在采用QUIC的应用(比如基于HTTP/3的网站、某些视频流)时感受不到好转,成因就在这里——两种UDP传输量经过了不同的处理管道。

bash
# 核查某个应用采用的UDP端口和协议
# QUIC一般采用UDP 443
ss -tunlp | grep 应用进程名

# 抓包观察UDP传输量的行为模式
# QUIC的包一般较大,且有TLS握手的特征
tcpdump -i eth0 -n udp port 443 -c 50

协议的边界与选择

追根究底,TCP 与 UDP 在加速上的差别,源自两者对应用层的承诺不同。TCP 承诺可靠、有序,于是加速器只能靠分段把这些承诺附带的时延成本隔离出去;UDP 不作承诺,看上去空间更大,实际可做的事更少——不能假设包的语义、不能重排、不能随便加延迟,活动范围基本限于路径优化和少量冗余。

这一点直接决定了谁该配什么手段。网页和 API 调用走 TCP,要压的是握手时延与窗口爬升时间;游戏与实时通信走 UDP,要压的是丢包率和路径抖动。若是把照着 TCP 设计的那套套到 UDP 上——比如强行做分段中继——结果要么牺牲了实时性,要么直接因为协议对不上而建不了连接。

反过来,若试图用UDP的”尽力而为”逻辑去加速TCP——比如只做通路转发不做接入分段——那等于放弃了所有TCP层面的调优有可能,退化为一个纯粹的VPN。

理解两个协议在设计上的取舍,不是为了背一份对照表,而是拿到一个加速方案时,能看清它的核心逻辑围着哪个协议转,以及它与你实际流量的匹配程度。两者不可互换,偏偏多数用户并不清楚自己跑的是哪一个。动手之前先把流量的协议构成查清楚,比只盯着各家的延迟数字有用得多。

作者

狗急加速器技术团队

协议该怎么选才省心

所谓稳定,是节点会自己换。狗急加速器把选路做成持续动作,每条专线的时延、抖动、丢包都在评估范围内,最优解变了就立刻跟着变。

读到这里可以看出,TCP 与 UDP 并非谁替代谁,而是各自扛住不同场景:长连接考验稳定性,实时交互更看抖动控制。真正麻烦的不是理论,而是你得在不同网络里反复切换去验证。

狗急加速器对此的处理是:把协议与线路的组合做成可自动切换的策略集,底层依据实时丢包与延迟表现调整,上层保留一键连接的简单操作。不必先读懂协议再去用工具,这也是我们做客户端时最在意的一点。

用一次实测判断该不该换协议

与其在理论上比较两种协议,不如做一次对照测试:固定同一个目标、同一时段,分别在两种模式下跑三分钟,记录均值、抖动与丢包三个数字。

判断标准也很简单——如果你主要做实时语音、游戏、直播,抖动和丢包改善更值得关注;如果是在传文件、拉代码库,那么吞吐是否符合预期才是重点。两个方向得出的结论可能完全相反,这很正常。

若两种模式差别不大,说明当前瓶颈不在协议,而在本地带宽或线路本身,这时候继续折腾参数是没用的。