本文同步发布于: https://www.pengrl.com/p/33330/ ,转载请注明出处,谢谢。
目录
- Introduction | 简介
- Conventions and Definitions | 约定和定义
- A QUIC Overview | 概述
- Connection Establishment Latency | 连接建立延时
- Flexible Congestion Control | 弹性拥塞控制
- Stream and Connection Flow Control | 流和链接两个层面的流量控制
- Multiplexing | 多路复用
- Authenticated and Encrypted Header and Payload | 认证和加密头部和负载
- Connection Migration | 连接迁移
Introduction | 简介
<!-- more -->
QUIC是一种新的基于UDP的多路复用、安全的传输协议,设计的基础来源于HTTP/2以及对它的优化。在构建以HTTP/2为首要应用层协议的同时,QUIC构建在许多传输和安全性的经验之上,并且实现了一个现代的、有吸引力的、通用的传输机制。QUIC提供等价于HTTP/2的多路复用和流量控制,等价于TLS的安全性,还有等价于TCP的面向连接语义,可靠性,拥塞控制。
QUIC完全工作于用户态,并且目前作为chrome浏览器的一部分提供给用户使用,可以快速部署和体验。已存协议的改进由于发布受到传统客户端和中间件,或操作系统较长的开发和发布周期的限制,已经被证明是非常困难的,但是QUIC作为构建于UDP之上的用户态传输协议却可以做到。
GUIC的一个重要目标是通过高速迭代设计出更好的传输协议。因此,我们希望以后把这些提取出来的优良的修改迁移到迭代周期要长得多的TCP和TLS中。
这个文档描述QUIC协议在标准之前的概念上的设计以及传输规格。相关联的文档描述了加密和协议握手[QUIC-CRYPTO],以及丢包恢复和拥塞控制[draft-iyengar-quic-loss-recovery]。包含更详细理论基础的文档和其他资源,在Chromium QUIC官方网站上 https://www.chromium.org/quic 。
QUIC标准的提案基于这些早期文档 [draft-hamilton-quic-transport-protocol], [draft-shade-quic-http2-mapping], [draft-iyengar-quic-loss-recovery], and [draft-thomson-quic-tls].
Conventions and Definitions | 约定和定义
所有QUIC中使用的整型数据,包括长度,版本,类型,都是小端字节序,并不是网络字节序。QUIC在动态大小的帧中并不强制类型对齐。
这个文档中使用的一些术语定义如下。
- "Client": 发起QUIC连接的端
- "Server": 接受QUIC连接的端
- "Endpoint": 客户端或服务端
- "Stream": 在QUIC连接内的一条用于传输双向流数据的逻辑通道
- "Connection": 两个QUIC端使用同一个上下文的可包含多个stream的会话
- "Connection ID": 一条QUIC连接的标识
- "QUIC Packet": 一个定义好格式的可被QUIC接收端解析的UDP包。在这个文档中QUIC包的大小取决于UDP负载的大小
A QUIC Overview | 概述
我们现在简单介绍QUIC的核心机制和优势。QUIC在功能上等价于TCP+TLS+HTTP/2
,但是实现是基于UDP的。QUIC相较于TCP+TLS+HTTP/2
的核心优势有:
- 连接建立的时延
- 弹性的拥塞控制
- 没有队列头部阻塞问题的多路复用
- 认证和加密的头和负载
- 流和连接两个层面的流量控制
- 连接迁移
Connection Establishment Latency | 连接建立延时
QUIC结合了加密和传输握手,降低了建立可靠连接的往返时间。QUIC连接大部分是0-RTT,意味着对于大部分QUIC的连接,数据可以不用等待server的回复而直接发送,相比较之下,TCP+TLS
在发送应用层数据前需要1到3次往返时间。
QUIC提供一个专门的流(Stream ID 1)用来处理握手,但是握手协议的细节超出了本文档的范围。完整的关于当前握手协议的描述,请查阅这个文档 https://docs.google.com/document/d/1g5nIXAIkN_Y-7XJW5K45IblHd_L2f5LTaDUDwvZ5L6g/edit 。QUIC当前的握手协议会在未来替换成TLS 1.3
。
Flexible Congestion Control | 弹性拥塞控制
相较于TCP,QUIC有可插拔的拥塞控制以及更丰富的信号,使得QUIC有能力提供更多的信息供拥塞控制算法使用。当前默认的拥塞控制是对TCP Cubic
的重新实现;我们正在测试其它可替代的算法。
一个关于QUIC提供更丰富信息的例子,对于每个包,不管是原始包还是重传包,都携带了一个新的包序号。这使得QUIC的发送端可以区分ACK包是用来请求重传包的还是请求原始包,避免了TCP重传的歧义。QUIC的ACK包还显式携带了包接收和ACK包发送的时间间隔,加上线性增长的包序号,可以精确计算出RTT往返时间。
最后,QUIC的ACK帧支持最多256个ack块,所以QUIC的重排序比使用SACK的TCP更有弹性,同时在乱序和丢包时可以在链路上保持传输更多的数据。客户端和服务端对于哪些包已经被对端收到也有更精准的认知。
Stream and Connection Flow Control | 流和链接两个层面的流量控制
QUIC实现了流和链接两个层面的流量控制,近似遵循HTTP/2
的流量控制。QUIC的流层面的流量控制工作如下。QUIC接收端通告每个流的绝对字节偏移直到接收端愿意接收数据。伴随着数据在特定的流上被发送,接收,传输,接收端发送WINDOW_UPDATE
帧来增加这个流的通告的偏移限制,使得对端可以在这个流上发送更多的数据。
作为对每个流的流量控制的补充,QUIC实现了连接层面的流量控制来限制一个QUIC接收端为一个连接所分配的总buffer大小。连接层面的流量控制的工作方式和流层面的流量控制相同,但是传输的字节数和更高层面的接收偏移是所有流的总和。
类似于TCP的自适应接收窗口,QUIC实现了同时基于流和连接的自适应的流量控制。如果发现限制了发送端的速度,QUIC会通过发送WINDOW_UPDATE
帧来增长窗口大小,如果接收程序很慢那么会限制发送端。
Multiplexing | 多路复用
基于TCP的HTTP/2会有队列头部阻塞的问题。因为HTTP/2的多路复用的多条流是基于TCP单个字节形式的流的抽象,丢失一个TCP分片会导致所有后续的分片被阻塞直到重传包的到来,而后续的分片有些属于其它无关的流。
因为QUIC从底层就为了多路复用而设计,丢包只影响特定的流。每个流的帧收到后可以立即分派给那个流,所以没丢包的流可以继续组包并且供应用层处理。
警告:QUIC目前通过HTTP/2 HPACK 的HTTP头压缩只发生在一个指定的stream(3)上,所以头部帧也有队列头部阻塞的问题。
Authenticated and Encrypted Header and Payload | 认证和加密头部和负载
TCP头以明文传输并且没有经过认证,导致了TCP有很多劫持和头部篡改的问题,比如篡改接收窗口和重写包序号。这些问题有些是蓄意攻击,有时候是网络的中间件利用这些机制来尝试提高TCP的性能。然后,这些为了加强性能的中间件的努力限制了传输协议的改进,例如已知的MPTCP的设计和由它引起的部署问题。
QUIC包总是经过认证的并且负载完全加密。包头没有被加密的部分也需要经过接收端认证,这使得第三方无法修改任何一个QUIC包。QUIC保护了连接,避免了中间件对点对点通信的有意无意的干扰。
Caveat: PUBLIC_RESET packets that reset a connection are currently not authenticated.
警告:用于重置一个连接的PUBLIC_RESET
包目前没有被认证。
Connection Migration | 连接迁移
TCP连接用源IP,源端口,目的IP,目的端口的四元组来标识。一个常见的问题是当IP地址变更(比如从WiFi切换到手机网络)或端口变更(当客户端的NAT绑定超时导致服务端看到的客户端的端口发生变化)将导致连接不可用。MPTCP解决了TCP的连接迁移问题,但是它依然由于缺乏中间件的支持和操作系统的发布而受到限制。
QUIC连接使用一个由客户端随机产生的64bit的连接ID来标识连接,当IP地址发生变化或者NAT重新绑定了,QUIC的连接依然可以保持,因为连接ID并没有发生变化。而且QUIC为迁移的客户端提供了自动密码验证,一个迁移的客户端继续使用同一个会话key来加解密数据包。
如果连接明确指定使用四元组作为标识,比如服务端使用一个临时端口给客户端发送数据,QUIC有一个选项设置不发送连接ID以使得节约链路上的包大小。