QUIC协议----简单学习整理

引言

2022年6月,HTTP/3正式被标准化为RFC 9114,其将是HTTP超文本传输协议的第三个主要版本。HTTP协议作为一个简单的请求-响应协议,各个主要版本主要是在于优化传输效率及安全性方面进行优化改进。

目前来说,仍存在大量服务器使用HTTP/1.1协议,其特点是,每个请求会独立建立一个TCP连接,而浏览器通常都会对单个域名的连接数进行限制,当连接数量过多,后续的请求就会排队等待。实际中,某些网站会采用多域名的方式去规避上述问题,但每一个请求的TCP建连开销仍然存在。

HTTP/2 采用多路复用技术,解决上述问题,其在一个TCP连接上同时传输多个请求和相应消息,如此排队等待的问题就迎刃而解了,同时也减少了TCP连接过程。除了多路复用提高请求的并发能力之外,还支持服务端主动推送以及头部压缩。其优点很多,但仍存在固有问题,和HTTP/1.1一样,其传输层基于TCP协议,由于TCP协议的丢包重传机制,如果一个请求发生丢包,浏览器会不断重传该数据包,进而阻塞后续请求,这也就是TCP的队头阻塞问题。

HTTP/3采用QUIC协议代替TCP协议提供可靠性传输,QUIC协议是基于UDP协议的,并采用了流的概念,不同的请求通过不同的有序字节流传输,即同一连接下互不影响的逻辑信道。同时具有流ID和流偏移2个字段,使得数据包可以乱序传输,而正确组装。当出现丢包时,仅重传出现丢包的流即可,并不会阻塞其他请求的传输,也就没有队头阻塞的问题。

QUIC

QUIC 源于Quick UDP Internet Connections,而如今是一个独立协议名称。QUIC 是一种基于UDP的安全、可靠、多路复用的传输协议。QUIC 是一种面向连接的协议,它在客户端和服务器之间创建有状态的交互。

QUIC的握手过程包含了加密和传输参数的协商,其集成了TLS握手。握手过程会尽快地完成数据交换,在有前置通信或配置的情况下,可以做到立即发送数据(0-RTT)。QUIC通信是基于数据包的,大多数数据包中含有1个或者更多的帧,这些帧携带控制信息或用户数据,最后利用UDP在网络中传输。上层应用在使用QUIC连接中的有序字节流交换数据,其可以创建两种流:双向流,允许两端均发送数据;单向流,仅允许单个端发送数据。QUIC 连接并不严格绑定到单个网络路径。 连接迁移使用连接标识符(不同于传统的五元组,使用64位随机数作为标识)完成连接转移到新的网络路径。 只有客户端才能在目前版本的 QUIC 中迁移。 还允许在网络拓扑或地址映射发生变化后继续连接,例如可能由 NAT 重新绑定引起的变化。

在这里插入图片描述

QUIC = TLS + TCP+HTTP/2 其整合了TCP的可靠性,TLS的安全性以及HTTP/2多路复用的并发性。

数据格式

Packet

long packet header

Long Header Packet {
  Header Form (1) = 1,
  Fixed Bit (1) = 1,
  Long Packet Type (2),
  Type-Specific Bits (4),
  Version (32),
  Destination Connection ID Length (8),
  Destination Connection ID (0..160),
  Source Connection ID Length (8),
  Source Connection ID (0..160),
  Type-Specific Payload (..),
}

long packet header 用于在 1-RTT 密钥建立之前发送的数据包。当1-RTT 密钥建立后,发送方会切换回short packet header。long packet header格式被用于特殊的数据包,例如版本协商数据包,其个字段含义如下:

Header Form: 对于long packet header第一个字节的最高位必须设置为1。

Fixed Bit:只有版本协商数据包该位会置为0,但目前未被使用,该位为0的数据包目前不会被处理,设置为1

Long Packet Type: 第一个字节的接下来2位表示数据包的类型,0为Initial Packet,1为0-RTT,2为Handshake Packet,3为Retry Packet,详细内容见最下方RFC文档

Type-Specific Bits: 第一个字节的低四位语义有数据包类型决定。

Version: QUIC 版本是跟在第一个字节之后的 32 位字段。 此字段指示正在使用的 QUIC 版本,并确定如何解释其余协议字段。

Destination Connection ID Length: 版本后面的字节包含其后面的目标连接 ID 字段的字节长度。8位无符号整数

Destination Connection ID: 连接标识ID

Source Connection ID Length: 源连接 ID 字段的字节长度。 8 位无符号整数。

Source Connection ID:源连接ID

Type-Specific Payload: 数据包的其余部分(如果有)是特定于类型的。


short packet header

Packet {
  Header Form (1) ,
  Fixed Bit (1) ,
  Spin Bit (1),
  Reserved Bits (2),
  Key Phase (1),
  Packet Number Length (2),
  Destination Connection ID (0..160),
  Packet Number (8..32),
  Packet Payload (8..),
}

1-RTT 数据包使用short packet header。 它在版本协商和 1-RTT 密钥协商后使用。

Header Form: 对于short packet header,第一个字节的最高位设置为0。

Fixed Bit: 只有版本协商数据包该位会置为0,但目前未被使用,该位为0的数据包目前不会被处理,设置为1。

Spin Bit:第一个字节 的第三个最高有效位表示延迟自旋位。

Reserved Bits: 下两位被保留。

Key Phase: 下一位表示密钥阶段,它允许数据包的接收者识别用于保护数据包的数据包保护密钥。

Packet Number Length: 最低有效两位包含数据包编号字段的长度,编码为无符号两位整数,比数据包编号字段的长度(以字节为单位)小 1。 即 Packet Number 字段的长度是该字段的值加一。

Destination Connection ID: 连接标识ID

Packet Number:字段的长度为 1 到 4 个字节。 数据包编号使用Header protection进行加密。

Packet Payload:1-RTT 数据包总是包含一个 1-RTT 加密的有效载荷。

Frame

Packet (负载部分)包含一个或多个Frame。Frame的类型由很多,如PADDING Frames、PING Frames、ACK Frames 、RESET_STREAM Frames、STOP_SENDING Frames、CRYPTO Frames、STREAM Frames、CONNECTION_CLOSE Frames、HANDSHAKE_DONE Frames等等。

Frame {
  Type (i) ,
  [Type-Specific Payload],
}

Type: 表示帧的类型。

QUIC Stream数据流是QUIC主要数据传输的载体,STREAM Frames是其必要组成单元,以此为例简单介绍。

STREAM Frame {
  Type (i) = 0x08..0x0f,
  Stream ID (i),
  [Offset (i)],
  [Length (i)],
  Stream Data (..),
}

Stream ID: 一个可变长度整数,表示流的流 ID。原版协议支出是一个62位的整数,一般认为1-4个字节长度

Offset: 一个可变长度整数,指定此 STREAM 帧中的数据在流中的字节偏移量。一般认为0-8个字节长度

Length: 一个可变长度整数,指定此 STREAM 帧中流数据字段的长度。一般认为0-2个字节长度

Stream Data: 被传递的指定流中的数据。

更详细的说明:https://zhuanlan.zhihu.com/p/405387352

握手

QUIC实现了快速握手,并把握手过程分为两种情况,分别是1-RTT和0-RTT。

在这里插入图片描述

1-RTT建连

若客户端没有服务器相关配置信息,只能进行1-RTT建连。

  1. 客户端主动向服务器发起连接,发送Inchoate CHLO 请求服务器配置参数。
  2. 服务器收到CHLO后,回复REJ(rejection)消息,其中含有服务器配置参数。
  3. 客户端向服务器发送complete CHLO消息,携带其生成的公开数,此时客户端已经可以根据服务端配置信息和自身选择的随机数,计算出初始密钥。
  4. 服务器收到complete CHLO消息,利用客户端的公开数计算出初始密钥,并向客户端回复用初始密钥加密的的SHLO消息,其含有一个服务器生成的临时随机数,用于生成会话密钥。
  5. 客户端收到SHLO消息,并用初始密钥解密,进而生成会话密钥。
  6. 客户端和服务器之前,利用会话密钥进行加密通信。

QUIC集成了TLS1.3,在协商完初始密钥后即会同时发送业务数据,并在更新会话密钥后切换到使用会话密钥,所有仅有1-RTT时间的延时。

0-RTT

如上所述,如果客户端缓存有服务器配置信息,可以直接发送complete CHLO消息,并发送加密数据。服务器收到消息后,会用初始密钥解密数据,并产生随机数用于生成会话密钥,并回复携带随机数的SHLO消息,客户端利用该随机数生成会话密钥,客户端和服务器之前,利用会话密钥进行加密通信。

在初始密钥后,再协商出一个最终的会话密钥,其目的是为了获取前向安全特性,服务端的后面生成的这份公私钥是临时生成的,不会保存下来,也就杜绝了密钥泄漏导致会话数据被恶意收集后的被解密的风险。

QUIC性能特点

建连更快

QUIC建连时间大约0~1 RTT,在两方面做了优化,一是传输层使用了UDP,相比于TCP减少了1RTT的三次握手的建连时间。二是加密协议采用了TLS 协议的最新版本TLS 1.3,相对之前的TLS 1.1-1.2,TLS1.3允许客户端无需等待TLS握手完成就开始发送应用程序数据,可以支持0-RTT和 1-RTT。

对于QUIC协议,客户端第一次建连的握手协商需1-RTT,而已建连的客户端重新建连可以使用之前协商好的缓存信息来恢复TLS连接,仅需0-RTT时间。因此QUIC建连时间大部分0-RTT、极少部分1-RTT,相比HTTPS的3-RTT的建连,具有极大的优势。

避免队头阻塞的多路复用

QUIC也支持多路复用,相比HTTP/2,QUIC的流与流之间完全隔离的,互相没有时序依赖。如果某个流出现丢包,仅重传丢包的流即可,不会阻塞其他流数据的传输和应用层处理,所以其并不会造成队头阻塞。

连接迁移

任何一条 QUIC 连接不再五元组作为标识,而是以一个 64 位的随机数作为 ID 来标识,这样就算 IP 或者端口发生变化时,只要 ID 不变,这条连接依然维持着,上层业务逻辑感知不到变化,不会中断,也就不需要重连。由于这个 ID 是客户端随机产生的,并且长度有 64 位,所以冲突概率非常低。

可选的拥塞控制算法

Cubic、BBR、Reno等拥塞控制算法,也可以根据具体的场景定制私有算法。

两级流量控制

QUIC同样采用了滑动窗口机制,在Connection和Stream两个级别分别进行流量控制。 用公式表示就是: connection可用窗口 = stream1可用窗口 + stream2可用窗口 + streamN可用窗口

前向纠错(FEC)

QUIC支持前向纠错,通过增加冗余数据,使数据包具有自动纠错的能力,可以减少重传次数,提升传输效率。

QUIC发展的一些问题

摘选自https://mp.weixin.qq.com/s/Ogfj0QlLF17sD60L3pwYXw

集成难度

无论是在客户端还是服务端,QUIC协议的集成并非一件易事。如果当前使用的网络不支持QUIC,意味着我们需要修改应用程序来适配网络库的调整。这往往并不是应用迭代的出发点。

下面让我们来看看客户端和服务端在集成QUIC协议时需要考虑的问题:

客户端

  • 应用适配成本和收益之间的权衡。
  • 过渡期可能还需要新旧网络库都存在,方便降级容错,增加应用体积。
  • 不同的QUIC库的接口并不统一,不像Socket统一接口具备移植性。

服务端

  • 网络事件模型需要适配QUIC协议栈做调整,同时还要考虑和TCP的兼容。
  • 后端架构面临调整,4层Load Balancer是否支持QUIC,HTTP/3的QUIC流量如何换成HTTP/1转给Backend Service。
  • 需要考虑到多Region、多节点之间的QUIC连接复用和连接迁移。
  • 服务端QUIC流量的能耗比,如何做到和TCP一样的能耗性能。

QUIC协议栈性能

对比已经发展了三十多年的TCP协议,新兴的QUIC协议在协议栈实现的工程上还有很多优化的事情要做,根据Google 2017年公开的数据,当时QUIC同等流量的CPU消耗是TCP的2倍之多。QUIC协议栈的性能痛点主要有:

  • UDP数据包收发性能
  • 数据装包、拆包处理性能
  • 数据包解析性能
  • ACK处理性能
  • 加、解密性能
  • 其他流程处理的性能:数据包Pacing、CC算法、内存使用等

UDP数据包性能

UDP数据包在内核接收发送上一直没有得到和TCP数据包一样的优化待遇,UDP收发占据了QUIC协议栈比较大的消耗。

  • 原始的sendto/write的UDP Socket接口性能很弱。
  • 批量收发数据sendmsg/sendmmsg提升不够明显。
  • 内核GRO/GSO可以提升性能,但还不够。
  • 内核XDP或者DPDK可大幅提升性能,但程序改造量极大。
  • 硬件NIC Offload UDP收发能终极优化,同样程序改造量极大。

UDP被运营商QoS限制

国内运营商确实会对UDP流量做些QoS的限制,但是能够被QoS限制的比例微乎其微,可以完全忽略。运营商这么做主要基于两个原因:

  1. UDP流量五元组在NAT状态上连接老化的时间控制不够精确,时间设置太长会破坏低频通信的UDP连接,太短会导致UDP连接消耗比较多的设备性能。一般会选择一个折中的经验值,这就会伤害一些特定场景的UDP流量了。

  2. 运营商设备上包分类的优先级队列对于UDP五元组的管理比较困难,因为UDP的五元组会频繁变动,只能眼睁睁看着UDP流量挤占各级队列,却没办法实施精确地控制。一般来说,运营商会在特定时间段或者特定负载情况下对UDP流量做全局限制。

QUIC Datagram——QUIC的非可靠数据报文传输扩展

QUIC v1(RFC9000)提供了一个安全、可靠、多路复用的传输方案,QUIC Stream数据流是QUIC主要数据传输的载体,可靠传输是其需要保证的基本功能。

但是有些应用场景并不需要严格的可靠传输,例如实时音视频、在线游戏等。现在这些场景有些是直接基于自定义UDP或者WebRTC实现的。自定义UDP实现传输层功能的话比较麻烦,工程量大,有时候为了安全考虑还需要加上DTLS支持,而WebRTC的建立数据传输通道流程也比较繁琐,WebRTC主要场景是为了P2P设计的,长远来看并不适合客户端服务端的场景。

因此,QUIC支持不可靠数据传输能够让QUIC协议的应用范围更广,适合更多的应用场景,而且QUIC之上的不可靠数据传输能够很好地复用QUIC的安全特性。

QUIC Datagram特点

  • 同一QUIC连接里面可以同时包含可靠Stream传输和不可靠数据传输,它们可以共享一次握手信息,分别可以作用于TLS和DTLS,可降低握手延迟。
  • QUIC在握手上比DTLS更加精准,它对每个握手数据包加上了超时重传定时器,能够快速感知握手包的丢失和恢复。
  • QUIC Datagram的不可靠传输也可以被ACK,这是一个选项,如果有ACK,可以让应用程序感知到QUIC Datagram的成功接收。
  • QUIC Datagram也适用于QUIC的CC。

这些特性能够让实时音视频流、在线游戏和实时网络服务等应用的传输得到极大的效率提升。

参考文献

QUIC RFC9000 https://quicwg.org/base-drafts/rfc9000.html

QUIC Datagram: https://datatracker.ietf.org/doc/html/draft-ietf-quic-datagram-06

QUIC协议的发展 https://mp.weixin.qq.com/s/Ogfj0QlLF17sD60L3pwYXw

QUIC 是如何解决TCP 性能瓶颈的 https://mp.weixin.qq.com/s/PZ1IbXe396b6gzmWYpFk-Q

<think>首先,用户的问题是关于TCP协议HTTP协议之间的关系及转换原理。我需要基于提供的引用内容来回答,但引用内容有些混乱。让我整理一下: - 引用[1]: 讨论了TCP和HTTP的关系,包括性能优化(如HTTP/1.1的持久连接、HTTP/2的多路复用、HTTP/3使用QUIC),并总结TCP是基础传输层协议HTTP是应用层协议,它们协同工作。 - 引用[2]: 是关于TCP协议的深入理解,强调学习TCP的困难,但内容不直接相关。 - 引用[3]: 比较了TCP和UDP,指出TCP是面向连接的、可靠的、无大小限制但速度慢;UDP则相反。 用户的问题核心是“TCP协议HTTP协议之间的关系及转换原理”。我需要构建一个清晰、结构化的回答。 ### 回答结构 1. **介绍TCP和HTTP协议**:简要定义每个协议。 2. **关系**:解释它们如何交互,基于OSI模型或TCP/IP模型。 3. **转换机制**:描述数据如何从HTTP应用层通过TCP传输层传输。 4. **引用支持**:在适当的地方添加引用标识。 5. **生成相关问题**:在末尾添加相关问题。 ### 关键点从引用中提取 - 引用[1]: TCP为HTTP提供可靠的传输服务;HTTP定义Web通信规则;它们协同工作。 - 性能优化如持久连接和多路复用减少了TCP开销。 - HTTP/3使用QUIC基于UDP,解决TCP问题。 用户提到“转换机制”,这可能指的是数据如何从HTTP应用层封装到TCP段,然后通过网络传输。 ### 详细解释 - **TCP协议**:传输控制协议,工作在传输层。提供可靠、面向连接的服务,确保数据有序、无差错传输。 - **HTTP协议**:超文本传输协议,工作在应用层。定义客户端和服务器如何交换超文本(如网页)。 - **关系**:HTTP依赖于TCP进行数据传输。当浏览器发送HTTP请求时,它使用TCP连接来发送数据。TCP处理底层的数据分段、确认、重传等,而HTTP处理高层的请求/响应语义。 - **转换原理**:这涉及网络栈: - HTTP应用层生成消息(如GET请求)。 - 传输层(TCP)将消息分段成TCP段,添加端口号、序列号等。 - 网络层(IP)添加IP地址,形成数据包。 - 然后通过物理网络传输。 - 接收端反向处理:TCP重组段,HTTP解析消息。 引用[1]提到HTTP/1.1的持久连接减少了TCP连接建立/关闭的开销,HTTP/2的多路复用允许单个TCP连接处理多个请求,这优化了性能。 ### 回答步骤 1. **开头**:直接回答问题,概述关系。 2. **分层解释**:使用OSI模型或TCP/IP模型解释。 3. **具体机制**:描述HTTP消息如何通过TCP传输。 4. **优化和变体**:简要提及HTTP/1.1、HTTP/2、HTTP/3的差异。 5. **结尾**:总结并添加相关问题。 ### 系统级指令 - 使用$...$ for inline math, e.g., $port number$。 - 独立公式用$$...$$,但这里可能不需要很多数学。 - 中文回答。 - 生成相关问题。 - 添加引用标识,如[^1]。 ### 相关问题生成 基于主题: 1. TCP协议如何保证可靠性? 2. HTTP协议的发展历史是什么? 3. QUIC协议如何解决TCP的队头阻塞问题? 4. 在实际应用中,如何优化TCP和HTTP的性能? 5. TCP和UDP的主要区别有哪些? ### 完整回答框架 - 引言:简述TCP和HTTP的关系。 - 主体: - 分层模型解释。 - 转换机制:从HTTP到TCP的封装。 - 性能考虑。 - 结尾:总结。 - 相关问题。 确保回答真实可靠,基于引用。</think>### TCP协议HTTP协议之间的关系及转换原理 TCP(传输控制协议)和HTTP(超文本传输协议)是互联网通信中两个核心协议,它们协同工作以实现Web数据传输。简单来说,**TCP是底层传输层协议,负责可靠的数据传输;而HTTP是上层应用层协议,定义了Web通信的规则和格式**。两者之间没有直接的“转换”机制,而是通过分层模型(如TCP/IP模型)进行协作:HTTP消息被封装在TCP段中传输。下面我将逐步解释它们的关系和协作原理,确保内容清晰可靠。 #### 1. **协议分层与基本关系** 在TCP/IP模型中,网络通信分为四层: - **应用层(HTTP)**:定义数据格式和业务逻辑,例如HTTP请求(如`GET /index.html`)和响应(如状态码200)。 - **传输层(TCP)**:提供可靠、面向连接的服务,确保数据有序、无差错地传输。TCP通过端口号(如HTTP默认端口80)标识应用。 - **网络层(IP)**:处理路由和寻址。 - **链路层**:管理物理传输。 **关系总结**: - TCP是HTTP的基础传输协议HTTP不直接处理数据传输,而是依赖TCP建立连接、分段数据、处理重传和确认[^1]。 - HTTP是TCP的应用:HTTP定义了Web交互的语义(如请求方法GET/POST),而TCP负责底层字节流的可靠交付[^1]。 - 协同工作:例如,当浏览器访问网站时,HTTP生成请求消息,TCP将其封装成段(segment),通过IP网络传输;接收端TCP重组数据,HTTP解析内容[^3]。 这种分层设计使得HTTP可以专注于应用逻辑,而TCP处理传输可靠性,避免了应用层重复实现错误控制。 #### 2. **转换机制:从HTTP到TCP的封装过程** “转换机制”实质上是数据封装(encapsulation)过程,即HTTP消息被逐层包装到TCP段中。以下是典型步骤(以HTTP请求为例): 1. **HTTP层生成消息**: 应用层(HTTP)创建请求,例如一个简单的GET请求: ``` GET /index.html HTTP/1.1 Host: example.com ``` 这个消息是纯文本格式,定义了Web交互规则。 2. **TCP层封装数据**: - TCP将HTTP消息分割成适合网络传输的段(每段大小由MSS, Maximum Segment Size决定,通常约1460字节)。 - TCP添加头部信息,包括: - 源端口和目的端口(如源端口$ \text{src\_port} = 12345 $,目的端口$ \text{dst\_port} = 80 $)。 - 序列号(sequence number)和确认号(acknowledgment number),用于确保数据有序和可靠。 - 控制标志(如SYN、ACK、FIN),用于建立和关闭连接。 - 封装后,HTTP消息变为TCP段: $$ \text{TCP段} = \text{TCP头部} + \text{HTTP消息载荷} $$ 3. **下层传输**: TCP段被传递给网络层(IP),添加IP头部(源/目的IP地址),形成IP数据包。最终通过链路层(如以太网)发送。 4. **接收端处理**: - 接收方TCP层重组段(使用序列号),检查数据完整性(通过校验和),并发送ACK确认。 - 重组后的数据传递给HTTP层,解析为响应(如HTML内容)。 **关键点**: - **连接建立与关闭**:HTTP通信前,TCP需完成“三次握手”(SYN, SYN-ACK, ACK)建立连接;结束时通过“四次挥手”关闭连接。这确保了可靠传输,但引入了延迟[^1]。 - **无直接转换**:HTTP和TCP不是相互转换,而是HTTP消息作为载荷(payload)嵌入TCP段。TCP不“理解”HTTP内容,只负责字节流传输。 - **端口机制**:端口号(如80 for HTTP)是TCP标识应用的关键,使得多个应用(如HTTP、FTP)可共享同一IP[^3]。 #### 3. **性能优化与变体** TCP和HTTP的协作可通过协议优化减少开销: - **HTTP/1.1持久连接(Keep-Alive)**:复用TCP连接处理多个HTTP请求,避免频繁建立/关闭连接的开销,提升效率[^1]。 - **HTTP/2多路复用**:在单个TCP连接上并行传输多个HTTP请求/响应,解决队头阻塞(Head-of-Line Blocking)问题,但TCP层仍可能因丢包导致整体延迟[^1]。 - **HTTP/3和QUIC**:为彻底解决TCP缺陷,HTTP/3改用QUIC协议(基于UDP),提供类似TCP的可靠性,但减少了握手延迟和队头阻塞,实现了“协议升级”而非转换[^1]。 这些优化体现了HTTP演进如何适应TCP特性,但核心关系不变:TCP提供传输基础,HTTP构建应用逻辑。 #### 总结 TCP和HTTP的关系是分层协作:TCP作为传输层协议,为HTTP提供可靠、面向连接的数据通道;HTTP作为应用层协议,利用TCP传输定义好的Web消息。转换机制本质是封装过程,而非协议间的主动转换。理解这一点有助于诊断网络问题(如延迟分析)和优化Web性能[^1][^3]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值