当前位置: 首页 > ops >正文

quic协议与应用开发

quic为什么出现?

quic主要是为了解决TCP协议的局限性而提出的,具体来说是要解决如下问题:

1. 加密连接建立时间长

TCP协议是传输层协议,而TLS是会话层协议,在Linux等主流操作系统中TCP在内核实现而TLS一般在用户态实现,因此基于TCP+TLS的典型加密连接至少需要2RTT才能完成建连。

2. 队头阻塞/多流建立时延

TCP协议中没有明确的流(stream)的概念,或者说TCP语境中流和连接是等价的。在需要并发传输多段数据的情况下,TCP需要建立多条连接才能实现多数据段的完全并行传输,而多连接的建立又会产生更多的时延,即使使用TCP fastopen也仍然会产生一次TLS握手时延。

并行传输的另一个实现方式是多请求复用单个连接。虽然在HTTP2等协议中支持多请求流并行收发,但这只是一个应用层的逻辑概念,在TCP传输中仍然只支持单流传输。由于TCP向应用层交付数据时是保证有序的,因此在单TCP连接上进行多请求数据并行传输时,只要有一个请求的报文丢失就会阻塞所有请求的数据交付。并行传输效果不稳定,且在实现中多逻辑流并发使用单连接socket容易产生并发正确性和性能问题。

事实上在广域网RDMA协议iWARP中,也有报文乱序交付设计与TCP按序交付规范相冲突的问题,iWARP规范中提出了修改TCP协议实现来实现按需乱序交付的能力,以提高数据交付性能。但这种修改让TCP协议的实现变的更加复杂,缺乏经过验证的标准实现,因此没有得到广泛支持和应用。

3. 网络切换与连接迁移

随着移动网络场景的普及,网络切换(主要是wifi到4G/5G移动网络)成为了一个高频场景。虽然4G/5G移动网已经支持了基站间的地址迁移,网内基站切换不会产生地址切换,但跨网络的切换仍然会造成设备网络地址的改变。TCP连接是以网络地址来标识的,地址切换意味着切换前的TCP连接全部失效,正在传输的数据流中断。这种情况下就需要应用层支持数据的断点恢复和续传,增加了应用开发成本和重复度。同时需要重建所有TCP连接,引入了额外的建连时延。

虽然TCP也支持Fast open特性,可以实现快速建连,但上层协议状态(例如TLS加密状态)仍然无法透明恢复。此外fastopen也不支持IP地址切换后使用。

quic协议的发展过程

2012年:QUIC(Quick UDP Internet Connections)协议由Google提出,旨在解决传统TCP协议在现代化网络环境中暴露的局限性,特别是在HTTP协议使用场景中。早期quic协议由google定义和实现,基于quic的http协议称作http-over-quic。

2015年:QUIC被提交至IETF标准化,逐步脱离Google的私有实现。

2018年:http-over-quic正式被命名为http/3,意味着下一代http协议完全基于quic传输协议

2021年:quic协议规范RFC9000正式发布

2022年:http/3协议规范RFC9114正式发布

可以看到,quic最初是用于解决http协议传输效率问题而提出的,之后成为了http下一代规范的指定传输协议。但quic本身也是一个标准的可靠加密传输协议,可以应用于其他网络传输场景。

quic协议实现原理

快速建连

1RTT:quic协议将可靠传输通道建连与TLS加密通道建连结合,在一个报文中携带两种握手信息(quic initial + tls client/server hello),从而只需要一次交互就能完成可靠加密传输通道建立,耗时1RTT。

0RTT:在通过1RTT建立成功后,可以基于TLS的会话复用机制,实现0RTT的建连。在这种模式下,quic initial协商报文与数据载荷报文同时发出,其中载荷报文复用已建立的TLS会话密钥加密。如果对端接受quic initial报文中的会话复用协商,就能处理直接处理载荷报文。需要注意的是0RTT机制允许在未协商的情况下处理和缓存数据,容易受到重放攻击和flooding攻击,需要仔细考虑使用场景和策略。

单连接多流复用

quic的最小逻辑传输单元是流,而不是连接。建立一条quic连接后,可以在相同五元组连接上建立多条逻辑传输流。流不需要专门的协商创建流程,使用新的stream id传输stream帧就可以在两端建立新的流。

quic连接的每条流有独立的缓存、排序和重传状态,每条流内部保证数据的有序可靠交付。

每条流有独立的接受窗口(window)用于流量控制,这是因为每条流对应的处理逻辑不同,处理能力也有差异。

但拥塞控制算法和拥塞窗口(cwnd)是连接级别的,因为同一条连接的网络转发路径基本相同,拥塞对连接中的所有流都存在。

连接迁移

quic连接建立时,两端会分别为这个连接分配connection id并同步给对方。在quic协议内连接的标识是双方分配的connection id,而非五元组信息。这就为跨五元组的连接迁移提供了支持基础。

在客户端的ip发生变化后,通过如下流程进行连接迁移:

1. 使用新IP+原connection id继续发送数据帧

2. server收到数据帧发现client的ip发生改变,向client发送PATH CHALLENGE帧

3. client向server回应PATH RESPONSE帧

4. server验证PATH RESPONSE中的路径内容,迁移完成

TCP真的不行吗?

从上面介绍的quic协议核心特性实现来看,在TCP的基础上进行扩展其实也是可以实现类似效果的。

  • 快速建连:可以在TCP的三次握手报文中增加对TLS1.3协商的扩展选项,来实现1RTT协商建连
  • 多流复用:可以通过TCP fastopen+TLS 会话复用,实现0RTT的后续流快速建立和并行传输
  • 连接迁移:可以通过扩展改造TCP fastopen机制,实现连接连接标识在IP变化后仍能被识别,并且将新建连接关联到旧连接数据上。

但这样的改造在TCP上面临的阻力会非常大。TCP协议是一个古老而复杂的协议,并且作为网络的主要传输协议被实现在各种操作系统内核中。不管是重新定义和扩展TCP协议,还是修改扩展内核协议栈,都基本不可能被标准组织和内核社区接受成为标准实现,也就无法推广应用。

此外,虽然TCP可以通过快速建立多条连接来实现类似多流复用的效果,但毕竟还是需要建立多条连接的,对端口资源的占用和建连协商验证的资源开销是无法避免的。因此无法完全达到和quic相同的效果。这是TCP面向连接可靠交付的核心特质决定的,无法修改。MPTCP中的连接有子流的概念,其实每个子流也是一个独立的TCP连接。

因此,在TLS全流量加密+HTTP多流传输的刚需场景下,选择在用户态重新定义可靠加密会话传输协议,基于限制最小的UDP协议成为了一种自然的选择。

但如果是在用户态协议栈中,基于TCP协议扩展来实现quic类似的特性就重新成为了可能的选项。用户态协议栈完全独立于内核,可以自定义实现方式和扩展特性。与UDP协议相比,TCP协议可以通过TCP选项头协商来实现与标准TCP协议的兼容和自动回落,同时避免部分运营商和转发设备对UDP报文的针对性丢包和低优处理,因此也有其存在价值,值得考虑。

http://www.xdnf.cn/news/18080.html

相关文章:

  • 实战架构思考及实战问题:Docker+‌Jenkins 自动化部署
  • [Oracle数据库] Oracle 进阶应用
  • 基于 ONNX Runtime 的 YOLOv8 高性能 C++ 推理实现
  • 网络间的通用语言TCP/IP-网络中的通用规则2
  • CMakeLists.txt 学习笔记
  • Java中的128陷阱:深入解析Integer缓存机制及应对策略
  • 深度解析阿里巴巴国际站商品详情 API:从接口调用到数据结构化处理
  • 8.18决策树
  • Unity引擎播放HLS自适应码率流媒体视频
  • 代码随想录算法训练营四十五天|图论part03
  • 上网行为安全管理与组网方案
  • 在阿里云 CentOS Stream 9 64位 UEFI 版上离线安装 Docker Compose
  • 深入解析Kafka消费者重平衡机制与性能优化实践指南
  • Windows从零到一安装KingbaseES数据库及使用ksql工具连接全指南
  • 【Goland】:Map
  • 【音视频】ISP能力
  • iOS 应用上架全流程实践,从开发内测到正式发布的多工具组合方案
  • Qt笔试题
  • HTML应用指南:利用POST请求获取全国华为旗舰店门店位置信息
  • 蓝桥杯算法之搜索章 - 6
  • Python入门第8课:模块与包的使用,如何导入标准库与第三方库
  • vite+react+antd,封装公共组件并发布npm包
  • lamp架构部署wordpress
  • 【新手易混】find 命令中 -perm 选项的知识点
  • Vue2篇——第六章 Vue 路由(VueRouter)全解析
  • 【AI论文】观察、聆听、记忆与推理:具备长期记忆能力的多模态智能体
  • 神经网络显存占用分析:从原理到优化的实战指南
  • 51c大模型~合集170
  • 窗口看门狗(WWDG)
  • SpringBoot--JWT