谷歌出品!读懂 QUIC 协议:更快、更高效的通信协议

QUIC结构

QUIC协议模型如下图所示,其放弃了TCP∕IP网络中使用五元组(源IP,源端口,目的IP,目的端口,协议标识符)来唯一标识一条连接的方式,而使用一个全局唯一的随机生成的ID(即Connection ID) 来标识一条连接。

由低向上分层讨论QUIC协议:

•UDP层:在UDP层传输的是UDP报文,此处关注的是UDP报文荷载内容是什么,以及如何高效发送UDP报文;

•Connection层:Connection通过Connection ID来确认唯一连接,connection对packet进行可靠传输和安全传输;

•Stream层:在相应的Connection中,Stream通过Stream ID进行唯一流确认,并对stream frame进行传输管理。

Quic协议相关术语
  • 数据包(Packet):QUIC 协议中一个完整可处理的单元,可以封装在UDP 数据报(datagram)中。多个QUIC 数据包(packets)可以封装在一个UDP 数据报(datagram)中。
  • 帧(Frame):QUIC 数据包(packet)的有效载荷(payload)。
  • 端点(Endpoint):在QUIC 连接中生成、接收和处理 QUIC 数据包(packets)的终端。QUIC中只有两端点(endpoints):客户端(client)和服务端(server)。
  • 客户端(Client): 创建QUIC 连接的端点。
  • 服务端(Server): 接收QUIC 连接的端点。
  • 地址(Address):未经限定使用时,表示网络路径一端的IP 版本、IP地址和 UDP 端口号的元组。
  • 连接ID(Connection ID): 用于标识端点 QUIC 连接的一种标识符。每个端点(endpoint)为其对端(peer)选择一个或多个连接 ID,将其包含在发送到该端点的数据包(packets)中。这个值对peer 不透明。
  • 流(Stream):QUIC 连接中有序字节的单向(unidirectional)或双向(bidirectional)通道。一个QUIC 连接可以同时携带多个流。
  • 应用程序(Application):使用QUIC 发送或者接收数据的实体。
UDP层
UDP荷载大小

•荷载大小受限于3个对象:QUIC协议规定;路径MTU;终端接受能力

1、QUIC不能运行在不支持1200字节的单个UDP传输网络路径上 QUIC规定initial包大小不得小于1200,如果数据本身不足1200(比如initial ack),那么需要用padding方式至少填充到1200字节

2、QUIC不希望出现IP层分片现象本要求意味着udp交给IP层的数据不会大于1个MTU,假设mtu为1500,ipv4场景下,udp的荷载上限为1472字节(1500-20-8),ipv6下,udp荷载上限为1452(1500-40-8)。QUIC建议使用PMTUD以及DPLPMTUD进行mtu探测。在实战中,我们建议设置IPv6的MTU为1280,大于这个值,某些网络会存在丢包现象。

3、终端能接受 transport paraments的max_udp_payload_size(0x03)的是终端接受单个udp包大小的能力,发送端应当遵从这一约定。

UDP荷载内容

UDP荷载内容即为QUIC协议中的packet。协议规定,如果不超过荷载大小的限制,那么多个packet可以组成一个UDP报文发出去。在QUIC实现中,如果每个UDP报文只包含一个QUIC packet,会更容易出现乱序问题。

高效发UDP包

和tcp不同,QUIC需要在应用层就完成UDP数据组装,且每个udp报文不大于1个mtu,如果不加以优化,比如每个包直接用sendto/sendmsg发送,势必会造成大量的系统调用,影响吞吐

1、通过sendmmsg接口进行优化,sendmmsg可以将用户态的多个UDP QUIC包通过一次系统调用发到内核态。内核态对于每个UDP QUIC包独立作为UDP包发出去

2、在1.)解决了系统调用次数问题,开启GSO可以进步一分包延迟到发给网卡驱动前一刻,可以进一步提高吞吐,降低CPU消耗。

Connection层

上节说到,1个udp报文里传输的其实是一个或多个QIUC协议打包的packet。所以在Connection这一层面,其实是以packet为单位进行管理的。一个packet到来,终端需要解析出目标Connection ID(DCID)字段,并将该packet交给找到对应的QIUC connection。一个packet是由header加payload两部分组成。

Connection ID

相较于TCP/IP使用五元组标识一条连接,QIUC在Connection层采用客户端随机产生的64位随机数作为Connection ID标识连接,这样IP或者端口发生变化时,只要ID 不变,这条连接依然维持,可以做到连接平滑迁移。

连接建立时使用UDP端口号来识别指定机器上的特定server,而一旦建立,连接通过其connection ID关联。

上图左边是HTTPS的一次完全握手的建连过程,需要3 个 RTT。就算是Session Resumption,也需要至少 2个 RTT。而 QUIC 由于建立在UDP 的基础上,同时又实现了 0RTT的安全握手,所以在大部分情况下,只需要0 个 RTT就能实现数据发送,在实现前向加密的基础上,并且 0RTT 的成功率相比TLS 的 Sesison Ticket要高很多。QUIC握手(handshake)合并了加密和传输参数的协商,只需要1-RTT 即可完成握手,提升了建立连接到交换应用程序数据的速度。第二次连接时,可以通过第一次连接时获取到的预共享密钥(pre-shared secret)立即发送数据(0-RTT)。

安全传输

QUIC的安全传输依赖TLS1.3,而boring ssl是众多quic实现的依赖库。协议对Packet的头部以及荷载均进行了保护(包括packet number)。TLS1.3提供了0-RTT的能力,在提供数据保护的同时,能在第一时间(服务端收到第一个请求报文时)就将Response Header发给客户端。大大降低了HTTP业务中的首包时间。为了支持0-RTT,客户端需要保存PSK信息,以及部分transport parament信息。

安全传输也经常会涉及到性能问题,在目前主流的服务端,AESG由于cpu提供了硬件加速,所以性能表现最好。CHACHA20则需要更多的CPU资源。在短视频业务上,出于对首帧的要求,通常直接使用明文传输。

Transport Paramenter(TP)协商是在安全传输的握手阶段完成,除了协议规定的TP外,用户也可以扩展私有TP内容,这一特性带来了很大的便利,比如:客户端可以利用tp告知服务端进行明文传输。

可靠传输

QUIC协议是需要像TCP能够进行可靠传输,所以QUIC单独有一个rfc描述了丢包检测和拥塞控制的话题,

  • 丢包检测:

TCP 为了保证可靠性,使用了基于字节序号的 Sequence Number 及 Ack 来确认消息的有序到达。

QUIC 同样是一个可靠的协议,它使用 Packet Number 代替了 TCP 的 sequence number,并且每个 Packet Number 都严格递增。而 TCP ,重传 segment 的 sequence number 和原始的 segment 的 Sequence Number 保持不变,也正是由于这个特性,引入了 TCP 重传的歧义问题。

在普通的TCP里面,如果发送方收到三个重复的ACK就会触发快速重传,如果太久没收到ACK就会触发超时重传,而QUIC使用NACK (Negative Acknowledgement) 可以直接告知发送方哪些包丢了,不用等到超时重传。TCP有一个SACK的选项,也具备NACK的功能,QUIC的NACK有一个区别它每次重传的报文序号都是新的。

但是单纯依靠严格递增的 Packet Number 肯定是无法保证数据的顺序性和可靠性。QUIC 又引入了一个 Stream Offset 的概念,即一个 Stream 可以经过多个 Packet 传输,Packet Number 严格递增,没有依赖。但是 Packet 里的 Payload 如果是 Stream 的话,就需要依靠 Stream 的 Offset 来保证应用数据的顺序。

  • 拥塞控制:QUIC针对TCP协议中的一些缺陷,专门做了优化。QUIC 重新实现了TCP 协议的Cubic算法进行拥塞控制,并在此基础上做了不少改进。
  • 热插拔:tcp的拥塞控制需要内核态实现,而QUIC在用户态实现,因此QUIC 修改拥塞控制策略只需要在应用层操作,并且QUIC 会根据不同的网络环境、用户来动态选择拥塞控制算法。
  • 前向纠错 FEC:QUIC 使用前向纠错(FEC,Forward Error Correction)技术增加协议的容错性。一段数据被切分为10 个包后,依次对每个包进行异或运算,运算结果会作为 FEC 包与数据包一起被传输,当出现丢包时可根据剩余的包和FEC包推算出丢的包。
单调递增的Packet Number

TCP 为了保证可靠性,使用Sequence Number 和 ACK确认消息是否有序到达,但这样的设计存在缺陷。超时发生后客户端发起重传,随后接收到了ACK确认,但因为原始请求和重传请求所返回的ACK 消息一样,所以客户端无法分辨此 ACK 对应的是原始请求还是重传请求。如果客户端认为是原始请求的ACK,但实际上是左图的情形,则计算的采样 RTT 偏大;如果客户端认为是重传请求的ACK,但实际上是右图的情形,又会导致采样 RTT 偏小。采样 RTT 会影响超时重传时间(Retransmission TimeOut)的 计算。

QUIC解决了上面的歧义问题。与采用Sequence Number 标记不同的是,其使用的Packet Number标记严格单调递增,如果 Packet N 丢失了,那么重传时 Packet 的标识不会是 N,而是比 N 大的数字,比如N+M,这样发送方接收到确认消息时就能方便地知道 ACK 对应的是原始请求还是重传请求。

Connection层
更大的ACK block

一般来说,接收方收到发送方的消息后都应该发送一个 ACK回复,表示收到了数据。但每收到一个数据就返回一个ACK 回复太麻烦,所以一般不会立即回复,而是接收到多个数据后再回复,TCP SACK 最多提供 3个 ACK block。但有些场景下,比如下载,只需要服务器返回数据就好,但按照 TCP 的设计,每收到 3 个数据包就要返回一个ACK。而QUIC 最多可以捎带 256 个ACK block。在丢包率比较严重的网络下,更多的 ACK block 可以减少返回包的量,提升网络效率。

流量控制

TCP 会对每个 TCP 连接进行流量控制,通过滑动窗口进行实现。

QUIC 的流量控制有两个级别:连接级别和Stream级别,用于表达接收端的接受能力。

单条 Stream的流量控制如上图所示。Stream 还没传输数据时,接收窗口(flow control receive window)就是最大接收窗口(flow control receive window),随着接收方接收到数据后,接收窗口不断缩小。在接收到的数据中,有的数据已被处理,而有的数据还没来得及被处理。蓝色块表示已处理数据,黄色块表示未处理数据,这部分数据的到来,使得Stream的接收窗口缩小。

随着数据不断被处理,接收方就有能力处理更多数据。当满足(flow control receive offset - consumed bytes) < (max receive window / 2) 时,接收方会发送WINDOW_UPDATE frame 告诉发送方你可以再多发送些数据过来。这时flow control receive offset就会偏移,接收窗口增大,发送方可以发送更多数据到接收方。

由于QUIC协议允许多路复用,因此Stream 级别的控制对防止接收端接收过多数据作用有限,更需要借助 Connection 级别的流量控制。

针对stream:

可用窗口数 = 最大窗口数 – 接收到的最大偏移数

针对connection:

可用窗口数 = stream1可用窗口数+ … + streamN可用窗口数

QUIC 的流量控制和TCP 有点区别,TCP为了保证可靠性,窗口左边沿向右滑动时的长度取决于已经确认的字节数。如果中间出现丢包,就算接收到了更大序号的Segment,窗口起始changdu也无法超过这个序列号。 QUIC 不同,就算此前有些 packet 没有接收到,它的滑动窗口也只取决于接收到的最大偏移字节数。

Stream层

Stream是一个抽象的概念,用以表示一个有序传输的数据流,而这些数据其实就是由Stream Frame排列构成。QUIC 使用帧(frames)进行端到端的通信。一个或多个帧(frame)被组装成一个 QUIC 包(packet)。在一个quic connection上,可以同时传输多条流,QUIC通过对多路传输的支持,解决了TCP中的队头阻塞问题。

在QUIC协议中,有序的概念仅维护在单个stream中,stream之间和packet都不要求有序,假设某个packet丢失,只会影响包含在这个包里的stream,其他stream仍然可以从后续乱序到达的packet中提取到自己所需帧交给应用层。

Stream头部

可以创建两种类型的流:双向流(bidirectional streams),允许客户端和服务端互相发送数据。单向流(unidirectional streams),允许单个端点(endpoint)发送数据。一个基于信用的方案(credit-based scheme)用于限制流的创建并限制可发送的数据量。stream的不同类型定义在HTTP3中得到了充分的利用。

Stream荷载

Stream的荷载即为一系列Stream Frame,通过Stream Frame头部的Stream ID来确认单个流。在TCP里,如果一个segment传递丢失,那么后续segment乱序到达,也不会被应用层使用,只到丢失的segment重传成功为止,因此TCP实现的HTTP2的多路复用能力受到制约。在QUIC协议中,有序的概念仅维护在单个stream中,stream之间和packet都不要求有序,假设某个packet丢失,只会影响包含在这个包里的stream,其他stream仍然可以从后续乱序到达的packet中提取到自己所需要的数据交给应用层。

Quic相关开源库
gQUICiQUIC
chromium:quic-client/server-demo模块封装了支持HTTPS的QUIC实现MsQuicMsQuic是IETF quic协议的Microsoft实现。它是跨平台的,用C语言编写,设计成一个通用的QUIC库。
chromium:net/quic模块封装QUIC在更底层模仿TCP Socket操作,在chrome75版本后被弃用,本次quic模块基于74-75版本的模块实现。quic-go使用Go语言来重写的QUIC协议实现库,从github上面看其对于iQUIC和gQUIC这两个分支流派都提供了支持。
quiche目前谷歌使用的QUIC开源代码库,将QUIC从chromium独立出来提供QUIC协议的支持,与iQUIC兼容。QuicwgIETF quic实现工作小组

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/649220.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MongoDB莫名崩溃的问题定位与解决纪实

MongoDB莫名崩溃的问题定位与解决纪实 国庆之前发布的软件版本一直运行正常&#xff0c;国庆之后&#xff0c;测试同事跑自动化测试脚本&#xff0c;发现该软件频繁异常&#xff0c;通过查看log发现&#xff0c;该软件使用的MongoDB崩溃了。 该软件是个Windows的桌面软件&…

【QT+QGIS跨平台编译】之十二:【libpng+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文件目录 一、libpng介绍二、文件下载三、文件分析四、pro文件五、编译实践一、libpng介绍 PNG(Portable Network Graphics,便携式网络图形),是一种采用无损压缩算法的位图格式,支持索引、灰度、RGB三种颜色方案以及Alpha通道等特性。 PNG使用从LZ77派生的无损数据压缩算…

Java类加载器

什么是类加载器? 1.1类加载器 作用 负责将.class文件&#xff08;存储的物理文件&#xff09;加载在到内存中 需要有个人把我们写的java文件编译后的字节码文件搬运到虚拟机上 1.2类加载的完整过程 1.2类加载的完整过程 类加载时机 简单理解&#xff1a;字节码文件什么时候…

网络协议与攻击模拟_09部署DHCP服务器

一、部署DHCP服务器 Windows server部署DHCP服务器 1、虚拟机网络架构理解 Vmware里面不同的虚拟机可以设置相同的Vmnet网络&#xff0c;也可以设置不同的Vmnet网络。两台虚拟机设置相同的Vmnet1网卡&#xff0c;可以看作为使用虚拟交换机将两台Vmnet1的虚拟机连接起来的。 …

java学习之路(1)-隐藏桌面图标从CMD命令中打开软件

1.找到文件所在路径&#xff1a; 2.将文件路径添加到环境变量中 3.winr 打开cmd 输入命令&#xff08;目录后面的QQScLauncher.exe&#xff09; 直接可以打开QQ软件&#xff0c;删除桌面图标&#xff0c;别人就找不到了&#xff0c;只能通过cmd命令或者是找到安装包所在位置 …

微服务入门篇:Eureka注册中心(作用,搭建Eureka客户端和服务端)

目录 1.提供者与消费者2.Eureka的作用3.搭建EurekaServer1.配置服务端2.配置客户端3.复制实例操作4.服务拉取 1.提供者与消费者 ①服务提供者:一次业务中&#xff0c;被其它微服务调用的服务。&#xff08;提供接口给其它微服务) ②服务消费者:一次业务中&#xff0c;调用其它微…

docker的资源限制(cgroup)

前瞻 Docker 通过 Cgroup 来控制容器使用的资源配额&#xff0c;包括 CPU、内存、磁盘三大方面&#xff0c; 基本覆盖了常见的资源配额和使用量控制。 Cgroup 是 ControlGroups 的缩写&#xff0c;是 Linux 内核提供的一种可以限制、记录、隔离进程组所使用的物理资源(如 CPU、…

雪亮工程视频智能监控方案,助力打造全方位、多层次视频监管体系

随着科技的不断发展&#xff0c;视频监控已经成为城市安全防范的重要手段之一。为了提高城市安全防范水平&#xff0c;各地纷纷开展“雪亮工程”&#xff0c;即利用视频智能监控技术&#xff0c;实现对城市各个角落的全方位、全天候监控。本文将介绍一种雪亮工程视频智能监控方…

Shell脚本⑤函数与数组

一.函数 封装的可重复利用的具有特定功能的代码 格式&#xff1a; 方法一&#xff1a; [function] 函数名 (){ 命令序列 [return x] #使用return或者exit可以显式的结束函数 } 方法二&#xff1a; 函数名(){ 命令序列 } 1.函数的调用方法 &#xff08;1&…

Tensorflow2.0笔记 - tensor排序操作

本笔记主要记录sort,argsort,以及top_k操作&#xff0c;加上一个求Top K准确度的例子。 import tensorflow as tf import numpy as nptf.__version__#sort,argsort#对1维的tensor进行排序 tensor tf.random.shuffle(tf.range(10)) print(tensor) #升序 print("tf.sort(d…

纯血鸿蒙来了,企业开发者应该关注什么

2024年对于鸿蒙来说是一个里程碑&#xff0c;鸿蒙将正式对外发布 HarmonyOS NEXT 5.0&#xff0c;而此前传言的系统将不再对开发者层面兼容Android等消息将成为定论。 为什么鸿蒙能有这个底气&#xff1f;因为研究机构TechInsights发布预测报告称&#xff0c;华为HarmonyOS将在…

【Chrome】浏览器怎么清除缓存并强制刷新

文章目录 1、正常刷新&#xff1a;正常刷新网页&#xff0c;网页有缓存则采用缓存。 F5 或 刷新键2、强制刷新&#xff1a;忽略缓存刷新&#xff0c;重新下载资源不用缓存。 CtrlF5 或 ShiftF5 或 CtrlShiftR3、在浏览器的设置里面清除所有数据

基于 Docker 搭建 Uptime-Kuma 一个极简风的应用监控

GitHub&#xff1a;https://github.com/louislam/uptime-kuma 一、uptime-kuma 介绍 Demo&#xff1a;https://uptime.wuhanjiayou.cn/ uptime-kuma 是一款开源的监控工具, 支持 TCP / PING / HTTP 等多种监控方式&#xff0c;可监测网站&#xff0c;数据库&#xff0c;Docker…

OpenHarmony—类型转换仅支持as T语法

规则&#xff1a;arkts-as-casts 级别&#xff1a;错误 在ArkTS中&#xff0c;as关键字是类型转换的唯一语法&#xff0c;错误的类型转换会导致编译时错误或者运行时抛出ClassCastException异常。ArkTS不支持使用语法进行类型转换。 当需要将primitive类型&#xff08;如num…

使用Spring Boot和Tess4J实现本地与远程图片的文字识别

概要&#xff1a; 在本文中&#xff0c;我们将探讨如何在Spring Boot应用程序里集成Tess4J来实现OCR&#xff08;光学字符识别&#xff09;&#xff0c;以识别出本地和远程图片中的文字。我们将从添加依赖说起&#xff0c;然后创建服务类以实现OCR&#xff0c;最后展示如何处理…

C++:组合、继承与多态

面向对象设计的重要目的之一就是代码重用&#xff0c;这也是C的重要特性之一。代码重用鼓励人们使用已有的&#xff0c;得到认可并经过测试的高质量代码。多态允许以常规方式书写代码来访问多种现有的且已专门化了的相关类。继承和多态是面向对象程序设计方法的两个最主要的特性…

小程序 样式 WXSS

文章目录 样式 WXSS尺⼨单位样式导⼊选择器⼩程序中使⽤less 样式 WXSS WXSS( WeiXin Style Sheets )是⼀套样式语⾔&#xff0c;⽤于描述 WXML 的组件样式。 与 CSS 相⽐&#xff0c;WXSS 扩展的特性有&#xff1a; 响应式⻓度单位 rpx样式导⼊ 尺⼨单位 rpx &#xff08;…

基于frp工具实现内网穿透,跨局域网远程SSH登录

文章目录 一.概述1.1 为什么要内网穿透&#xff1f;1.2 什么是frp&#xff1f; 二.frp安装管理流程2.1 frp下载2.2 部署2.3 通过systemd系统服务管理启动程序 三.frp配置测试&#xff08;通过SSH访问内网机器C&#xff09;3.1 服务端配置文件frps.toml修改3.2 客户端配置文件fr…

tcp/ip分层模型

文章目录 tcp/ip分层模型封装和分用 tcp/ip分层模型 上面这个图主要介绍了osi七层模型和tcp/ip五层模型&#xff08;有的资料上说的是tcp/ip四层模型&#xff0c;把物理层算在了硬件设备上&#xff0c;这篇文章还是按照五层模型来讲&#xff09;。但osi七层模型实现起来比较复杂…

代码随想录算法训练营第16天 | 104.二叉树的最大深度, 111.二叉树的最小深度 ,222.完全二叉树的节点个数

二叉树理论基础&#xff1a; https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE 104.二叉树的最大深度 题目链接&#xff1a;https://leetcode.cn/problems/maximum-depth-…