TCP 已经五十多岁了。
但它真正奇怪的地方不是“老”,而是:
它越来越难改了。
不是没人想改。
这些年 TCP 有过很多漂亮的升级:SACK、ECN、TCP Fast Open、Multipath TCP……问题是,代码写完了,标准有了,操作系统也支持了,最后却经常死在一个地方:路上。
这里的“路”不是网线,而是互联网中间那些你平时看不见的设备:防火墙、NAT、负载均衡、代理、企业网关、IDS/IPS。
它们不是 TCP 的设计者,却慢慢成了 TCP 的“隐形设计者”。
一个 RTT 的优化,为什么这么难?
TCP Fast Open 就是一个很典型的例子。
普通 TCP 要先三次握手,再传数据。TFO 的思路很简单:
能不能在 SYN 里直接带数据?
这样就能少等一次 RTT。
Linux 很早就支持了 TFO,RFC 7413 也在 2014 年正式发布。
技术上没什么问题。
问题在于:中间设备可能不认识它。
防火墙看到特殊 TCP 选项,可能直接丢弃;某些 NAT 或网络设备也可能错误处理。
于是 TFO 面临一个非常尴尬的现实:
不是不能用,而是不知道这条路能不能用。
所以它甚至需要 fallback:先试,如果发现这条路径不支持,就记住,下次老老实实走普通 TCP。
一个新特性的最佳实践,最后变成了:
如果互联网不喜欢你,那就假装自己不存在。
这其实就是 TCP 最大的问题:
两端可以升级,但中间的人不一定同意。
TCP 最大的问题不是老,而是僵化
这叫Protocol Ossification——协议僵化。
TCP 最初设计的时候,中间设备没那么聪明。
后来互联网越来越复杂,防火墙、NAT、代理、负载均衡器越来越多,它们开始观察 TCP 的 flag、option、序列号和连接状态。
慢慢地,一些原本只是“实现细节”的东西,变成了设备默认依赖的东西。
于是出现了一个非常荒诞的现象:
你修改协议本身没有问题,但你无法保证整个互联网接受你的修改。
这就是 Middlebox Ossification。
中间设备甚至不需要参与协议设计,只需要在某个位置说一句:
“我不认识这个。”
整个互联网就得考虑它。
所以 TCP 不是不能进化,而是:
每一次进化,都要先征得整个互联网的同意。
那不用 TCP 呢?
其实有人试过。
SCTP 在 1998 年就出现了,支持多宿主、多流、消息边界等特性。
但它有一个致命问题:
它既不是 TCP,也不是 UDP。
它是独立的 IP 协议。
于是防火墙、NAT、负载均衡器就开始犯难:
TCP?
不是。
UDP?
也不是。
那是什么?
SCTP:
协议号 132。
中间设备:
“没听过。”
于是一个很残酷的事实出现了:
一个协议技术上再漂亮,也不意味着互联网会让它通过。
这给 QUIC 上了非常重要的一课:
直接发明一个新的 IP 传输协议,可能比修改 TCP 更难。
所以 QUIC 选择了 UDP
UDP 很简单。
简单到几乎没有什么值得中间设备“理解”的东西。
它不是所有网络都放行,但相比一个全新的 IP 传输协议,它已经是现实互联网里最成熟的入口之一。
于是 Google 的工程师想:
TCP 的可靠传输、拥塞控制、多路复用都很好。
UDP 又足够普遍。
那我自己重新造一套。
于是 QUIC 出现了。
QUIC 本质上不是升级 TCP,而是绕开 TCP。
它借 UDP 作为外壳,在里面重新实现可靠传输、拥塞控制、流量控制、多路复用和 TLS。
这不是多么浪漫的设计。
更像是一条被现实逼出来的绕路:
TCP 改不了,那就不改 TCP。
为什么 QUIC 要把很多东西加密?
很多人认为 QUIC 加密只是为了安全。
其实还有一个非常重要的原因:
防止下一次协议僵化。
TCP 的教训是:
你让中间设备看得越多,它们就越容易开始依赖这些东西。
今天只是“观察”。
明天就可能变成“依赖”。
后天你想修改:
“不行,我们的设备不支持。”
所以 QUIC 尽量把传输层内部状态隐藏起来。
中间设备知道:
这里有一个 UDP 流量。
但不应该轻易看到 QUIC 内部的包号、ACK 范围、Stream 状态等细节。
这就是所谓的:
Ossification-resistant encryption——防僵化加密。
它的意义不仅是:
防黑客。
还有:
防止网络设备把今天的协议细节,变成明天无法修改的枷锁。
但 QUIC 也付出了代价
QUIC 绕开 TCP 的同时,也绕开了 TCP 五十多年积累下来的基础设施。
TCP 有成熟的内核实现、网卡卸载、GRO/GSO、TSO、零拷贝以及完整的监控体系。
QUIC 大量运行在用户空间,传输、加密、ACK、重传等逻辑都需要自己处理。
所以它并不是免费的。
CPU 成本、实现复杂度、运维成本都会增加。
另一个代价是可观测性。
以前网络工程师抓个 TCP 包,看 SEQ、ACK、Window、SACK,很多问题就能判断。
现在 QUIC:
抓包。
打开工具。
一堆密文。
不是说 QUIC 无法调试,而是:
整个网络可观测性体系都需要重新适应它。
所以 HTTP/3 为什么选择 QUIC?
不是因为 TCP 不能用了。
也不是因为 QUIC 在任何情况下都比 TCP 快。
更不是因为 QUIC 是一个完美协议。
真正的问题是:
TCP 越成功,越难改变。
几十年来,防火墙围着它建,NAT 围着它建,负载均衡器围着它建,操作系统围着它优化,网卡围着它做硬件卸载。
最后,这些东西共同形成了一堵墙。
于是出现了互联网最有意思的悖论:
TCP 越成功,越没人敢改它。
这就是为什么 QUIC 看起来不像 TCP 的“下一代”,反而像是从 TCP 旁边绕过去的一条新路。
TCP 是老水管。
QUIC 是从墙外重新接的一根管子。
新管子不一定更漂亮,也不一定更便宜,但至少有一件事:
它不用先说服整栋楼的人,同意你换水管。
所以 TCP 真正“死掉”的,不是生命。
它今天依然活得很好。
真正死掉的是:
它作为一个可以自由进化的协议,正在失去自由。
而 QUIC 的意义,也不只是“比 TCP 更快”。
它更像互联网对一个现实问题的回答:
既然旧路越来越难走,那就换一条路。
至于这条新路,几十年以后会不会也变成一座谁都不敢修改的老城?
那就是下一代工程师的故事了。