背景
一段时间以来被称为 HTTP-over-QUIC 的协议现在已经改变了名称,将正式成为 HTTP/3。这是由马克?诺丁汉(Mark Nottingham)最初的建议引发的
具体博客地址
为什么需要QUIC
随着移动互联网快速发展以及物联网的逐步兴起,网络交互的场景越来越丰富,网络传输的内容也越来越庞大,用户对网络传输效率和 WEB 响应速度的要求也越来越高。
但是传统的协议比如TCP,一直有如下缺点:
- 依赖于操作系统的实现导致协议本身僵化。
TCP 是由操作系统在内核层面实现的,应用程序只能使用,不能直接修改。虽然应用程序的更新迭代非常快速和简单。但是 TCP 的迭代却非常缓慢,原因就是操作系统升级很麻烦。
现在移动终端更加流行,但是移动端部分用户的操作系统升级依然可能滞后数年时间。PC 端的系统升级滞后得更加严重,windows xp 现在还有大量用户在使用,尽管它已经存在快 20 年。
服务端系统不依赖用户升级,但是由于操作系统升级涉及到底层软件和运行库的更新,所以也比较保守和缓慢。
这也就意味着即使 TCP 有比较好的特性更新,也很难快速推广。比如 TCP Fast Open。它虽然 2013 年就被提出了,但是 Windows 很多系统版本依然不支持它
- 建立连接的握手延迟大。
不管是 HTTP1.0/1.1 还是 HTTPS,HTTP2,都使用了 TCP 进行传输。HTTPS 和 HTTP2 还需要使用 TLS 协议来进行安全传输。这就出现了两个握手延迟:
1.TCP 三次握手导致的 TCP 连接建立的延迟。
2.TLS 完全握手需要至少 2 个 RTT 才能建立,简化握手需要 1 个 RTT 的握手延迟。
对于很多短连接场景,这样的握手延迟影响很大,且无法消除
- 队头阻塞
队头阻塞主要是 TCP 协议的可靠性机制引入的。TCP 使用序列号来标识数据的顺序,数据必须按照顺序处理,如果前面的数据丢失,后面的数据就算到达了也不会通知应用层来处理。
另外 TLS 协议层面也有一个队头阻塞,因为 TLS 协议都是按照 record 来处理数据的,如果一个 record 中丢失了数据,也会导致整个 record 无法正确处理。
概括来讲,TCP 和 TLS1.2 之前的协议存在着结构性的问题,如果继续在现有的 TCP、TLS 协议之上实现一个全新的应用层协议,依赖于操作系统、中间设备还有用户的支持。部署成本非常高,阻力非常大。
所以 QUIC 协议选择了 UDP,因为 UDP 本身没有连接的概念,不需要三次握手,优化了连接建立的握手延迟,同时在应用程序层面实现了 TCP 的可靠性,TLS 的安全性和 HTTP2 的并发性,只需要用户端和服务端的应用程序支持 QUIC 协议,完全避开了操作系统和中间设备的限制。
- 中间设备的僵化
可能是 TCP 协议使用得太久,也非常可靠。所以我们很多中间设备,包括防火墙、NAT 网关,整流器等出现了一些约定俗成的动作。
比如有些防火墙只允许通过 80 和 443,不放通其他端口。NAT 网关在转换网络地址时重写传输层的头部,有可能导致双方无法使用新的传输格式。整流器和中间代理有时候出于安全的需要,会删除一些它们不认识的选项字段。
TCP 协议本来是支持端口、选项及特性的增加和修改。但是由于 TCP 协议和知名端口及选项使用的历史太悠久,中间设备已经依赖于这些潜规则,所以对这些内容的修改很容易遭到中间环节的干扰而失败。
为什么QUIC能撼动TCP的霸主地位
QUIC 协议是 Google 提出的一套基于 UDP 的开源协议,它汇集了 TCP 和 UDP 的优点,传输高效并且可靠,解决了TCP目前遇到的困境。QUIC优点如下:
- 更新迭代更容易:
TCP 和 UDP 协议是操作系统内核实现的,部署进度慢。QUIC 直接基于客户端实现,能实现快速迭代更新 - 没有队头阻塞的多路复用:
TCP 为了保证可靠性,使用了基于字节序号的 Sequence Number 及 Ack 来确认消息的有序到达,数据必须按照顺序处理,可能会造成队头阻塞。HTTP2 支持多路复用,但是由于强制使用 TLS ,还存在一个 TLS 协议层面的队头阻塞,QUIC 最基本的传输单元是 Packet,不会超过 MTU 的大小,整个加密和认证过程都是基于 Packet 的,不会跨越多个 Packet。这样就能避免 TLS 协议存在的队头阻塞。Stream 之间相互独立,比如 Stream2 丢了一个 Pakcet,不会影响 Stream3 和 Stream4,所以也不存在 TCP 队头阻塞。 - 自由选择拥塞控制:TCP 的拥塞控制实际上包含了四个算法:慢启动,拥塞避免,快速重传,快速恢复,QUIC 协议当前默认使用了 TCP 协议的 Cubic 拥塞控制算法,同时也支持 CubicBytes, Reno, RenoBytes, BBR, PCC 等拥塞控制算法。从拥塞算法本身来看,QUIC 只是按照 TCP 协议重新实现了一遍,那么 QUIC 协议到底改进在哪些方面呢?主要有如下几点:
- 可插拔:应用程序层面就能实现不同的拥塞控制算法,不需要操作系统,不需要内核支持,即使是单个应用程序的不同连接也能支持配置不同的拥塞控制
- 扩展方便:应用程序不需要停机和升级就能实现拥塞控制的变更,我们在服务端只需要修改一下配置,reload 一下,完全不需要停止服务就能实现拥塞控制的切
-
更多的 Ack 块:TCP 的 Sack 选项能够告诉发送方已经接收到的连续 Segment 的范围,方便发送方进行选择性重传。 由于 TCP 头部最大只有 60 个字节,标准头部占用了 20 字节,所以 Tcp Option 最大长度只有 40 字节,再加上 Tcp Timestamp option 占用了 10 个字节 [25],所以留给 Sack 选项的只有 30 个字节。 每一个 Sack Block 的长度是 8 个,加上 Sack Option 头部 2 个字节,也就意味着 Tcp Sack Option 最大只能提供 3 个 Block。 但是 Quic Ack Frame 可以同时提供 256 个 Ack Block,在丢包率比较高的网络下,更多的 Sack Block 可以提升网络的恢复速度,减少重传量 -
握手更迅速:TCP 需三次握手才能建立连接,有等待时延,如果用了TLS 加密,还会进一步增加时延。QUIC 采用了类似于TCP Fast Open的设计,在之前已经连接过的情况下可以无需握手,直接开始传送数据,连接建立时延为0 -
连接保持:TCP 连接是由四元组标识的(源 IP,源端口,目的 IP,目的端口),当其中一项发生改变,都需要重新建立和服务端的 TCP 连接。QUIC 连接不再以 IP 及端口四元组标识,而是以一个 64 位的随机数作为 ID 来标识,这样就算 IP 或者端口发生变化时,只要 ID 不变,这条连接依然维持着。这就意味着:在IP地址和端口变化的情况下(比如从Wi-Fi切换到流量),可以无需重新建立连接,继续通信
QUIC 缺点
既然QUIC 如此优秀,但是为什么还是没有大量普及呢?有如下原因
QUIC 基于 UDP ,目前很多网络运营商会降低 UDP 包的优先级,使得 UDP 丢包率特别高- 支持QUIC协议的浏览器比较少
展望未来
原文链接
参考
博客 知乎
|