Flutter 之 HTTP3/QUIC 和 Cronet 你了解过吗?

news2025/1/10 2:15:09

虽然 HTTP3/QUIC 和 cronet 跟 Flutter 没太大关系,只是最近在整理 Flutter 相关资料时发现还挺多人不了解,就放到一起聊聊。

本篇也是主要将现有资料做一些简化整合理解。

前言

其实为什么会有 HTTP3/QUIC ?核心原因还是现有协议已经无法满足需求,说个最简单又不严谨的例子:

当你在家里拿着手机用 Wi-Fi 下片,这时候觉得饿了要下楼吃饭,然后你带着手机离开了家里,期间一直没有退出 App 的打算,这个过程手机流量会从 Wi-Fi 变成 5G 网络,那么网络链路就会变成了一个全新的网络环境,从 Wi-Fi 到 5G 会是全新的 IP 地址,那么作为新的链接, TCP 就无法复用之前的数据和状态,也就是之前链路就断了,那么下载行为可能就会被打断,而你直到温饱之后要用,才发现资源还没下载完成。

我们知道, HTTP/2 时代,每个网络请求我们都要经历多次 TCP 握手,特别现在基本都强制了 HTTPS ,所以 TLS 加密握手也不可或缺,但是在移动场景下,其实用户的网络环境极有可能在不停的发生变化,所以用户在移动过程中,TCP 链接极有可能被迫打断。

在 App 使用过程中,重启 TCP 连接会带来一些不好的体验,例如等待新的握手、重新开始下载、重建上下文等延迟,而 QUIC 其中就包括解决这一问题的实现,通过 connection migration 实现链路复用,后续我们会详细聊到。

QUIC

其实只要说到 HTTP/3 就离不开 QUIC (Quick UDP Internet Connections),因为 QUIC 是一个通用传输协议,它是 HTTP/3 的灵魂所在,而神奇之处也在于,它是运行在 UDP 的协议的基础上

大家对于 UDP 应该不陌生,因为相较于 TCP ,它相对不可靠,因为 UDP 不提供任何特性,例如它不会通过握手建立连接,如果包丢失也不会获得自动重传,所以它一直以来都被冠以「不可靠」的称号。

那么 UDP 有什么优点?那肯定是快~因为 UDP 不需要等待握手,也没有队头阻塞,所以它的性能一直很好,那 QUIC 建立在 UDP 之上就是为了性能吗

其实并不全是,或者是关键因素并不是,因为如果把 QUIC 作为一个直接运行在 IP 之上的全新独立协议,那么就意味着 HTTP/3 会无法兼容现有的许多硬件设备,这明显并不现实,但是如果构建在 UDP 上,那么 QUIC 就拥有更好的兼容和部署支持

所以最终落地的结果就是: QUIC 在 UDP 之上重新实现了一套「更高效的 “new TCP”」 的通用协议

当然,如果你硬要简单说 HTTP/3 是将 TCP 换成了 UDP 也说得通,只是并不是因为 UDP 更快,而是为了 QUIC 能更好兼容部署,并且 QUIC 本身就是一套基于 UDP 的全新的高级的 “TCP”

那么 QUIC 有哪些优秀的地方呢?其中就包括前面说的在移动环境下让连接可以保持更长时间

QUIC 支持连接迁移( connection migration )

我们前面知道了,当用户手机在 Wi-Fi 和 5G 网络进行切换时,TCP 链接会出现中断,如果我们定义 App 和服务器之间的链接是通过 「App IP + App 端口 + 服务器 IP + 服务器端口」 这样四个元素来表示一个链接,那么 Wi-Fi 和 5G 网络的时候,App 端的 IP 变了,那么对于服务端而言,这就是一个全新的链接,所以旧的 TCP 链接就无法被复用。

为了解决这个问题,QUIC 提出了连接标识符(CID, connection identifier),每个连接都在前面提到的四个元素之上分配了另一个 CID 编号,可以在 App-服务器端点之间来唯一标识它。

简单说,因为这里 CID 在 QUIC 中的传输层定义,所以它不会因为切换网络时发生改变,比如下图所示,一般情况下 CID 是包含在每个 QUIC 数据包的前端,而 CID 也是 QUIC header 中少数几个没有加密的数据。

通过 CID ,前面提到的四个元素里,就算 App IP 发生变化,QUIC 服务器和 App 只需要看下 CID,就能知道这其实还是之前的同一个连接,不需要重新握手,可以继续复用之前的下载状态,这也是前面提到过的 connection migration 。

当然,前面这个介绍相对简化,如何考虑到安全问题,CID 不会被直接使用,而是使用映射。

假设 App 和服务器都知道有 CID A、B 、C 都是映射到连接 X, 然后 App 可能会在 Wi-Fi 上会使用 A 标记数据包,而在 5G 上使用 B 标记 ,而映射的列表在 QUIC 中是完全加密,从而让黑客只知道 A、B、C,但是不知道 X 的存在。

当然,这也还是简化后的逻辑,只是为了更好理解,现实中 CID 的相关逻辑更加复杂,只是通过这些,大家应该就可以更快速理解 QUIC 为什么可以做到 connection migration 和其关键实现理念。

就这样,有了 QUIC 支持,在移动场景中,当网络切换时,可以看到如下图右侧使用 QUIC 手机很快便响应了请求,而左侧手机因为需要建立新的链路,所以需要等待超时后,重新握手成功再请求的效率对比。

TLS 集成

其实通过一开始的架构图,大家应该也可以看出来,和 HTTP/2 不同的是,QUCI 他直接集成了 TLS ,其目的就是加快和减少 HTTPS 请求是所需的时间。

因为在以前使用 HTTPS 请求时, HTTP 数据需要先由 TLS 加密,再由 TCP 传输,虽然 TLS 随着版本发展所需的加密握手次数已经得到优化,但是相比较起来,加密所带来的开销还是客观存在。

而在 QUIC 里就不一样了,QUIC 将 TLS 进行了封装,所以,对于 TCP 模式下 TLS 和 TCP 协议都需要单独握手, QUIC 将传输和加密握手合并为一次握手,节省了往返时间,但这也表明了 QUIC 必须使用 TLS, HTTP/3 下会是始终完全加密的状态,同时 QUIC 还加密它的(除了前面的 CID 等)数据包头字段,甚至传输层信息一般情况下都不能再被中间件读取。

所以,QUIC 默认深度加密,与之前的 TCP 相比,他也可以在一定程度节省 TLS 的开销,当然,QUIC 使用 TLS 单独加密每个数据包,而 TLS-TCP 可以同时加密多个数据包,所以 QUIC 也可能在高吞吐量的场景中变慢。

优化多路复用字节流

简单说,多路复用字节流就是单一 TCP 连接下载不同的资源,在传输时将不同文件的数据混合,比如 ABC 三种数据混合在一起传输。

而在 TCP 时代,TCP 是不知道多路复用字节流里数据的混合情况,也即是 TCP 不知道数据是 ABC,它直管传输数据,如果这时候 C 出现数据丢失, TCP 会认为整个数据传输出现丢失,从而导致整个链路里其他 AB 因为这个等待而变慢,这就是传说中的队头阻塞问题。

而 QUIC 的在某种意义上解决了传输层的队头阻塞问题,因为 QUIC 会知道有多路复用的多字节流存在,是真正意义上“理解了”多路复用,所以它可以在每个流的基础上执行丢包监测和恢复逻辑。

当然,这也造成了 TCP 和 QUIC 出现了本质的不兼容区别,QUIC 「理论上」来说是不兼容 HTTP/2 运行,因为 HTTP/2 还包括在单一 TCP 连接上运行多个流的概念。

其实 TCP 的设计目的从来不是在单一 TCP 上传输多个独立的文件,只是因为现实场景用到了,所以才有这样奇怪的兼容方式,而 QUIC 通过在传输层传输多个字节流以及在每个流基础上处理丢包问题,来解决 TCP 上一直存在的问题。

总的来说,QUIC 算是 TCP 的不兼容升级,而又由于它基于 UDP 实现,所以可以兼容已有的设备运行,并且集成了 TLS,默认全加密,支持 connection migration 等,在不可靠的网络场景下也可以实现更可靠的网络运行

QUIC 下的 Flutter :Cronet

既然我们知道 HTTP/3 和 QUIC 可以得到更好的体验,那就不得不说 Cronet,因为 Cronet 是 Chromium 网络堆栈,所以才被称为 Cronet ,它和 Chromium 使用相同的网络引擎。

使用 Cronet 最重要的意义是,它能够同时支持 TCP 协议和 QUIC 协议,一般情况下 App 发送请求时会说明“我支持 QUIC” ,然后服务端收到请求后,根据自身情况确实是否使用 QUIC 。

目前的说法是,只要 Cronet 知道了服务端支持 QUIC ,那么 Cronet 后续请求就会开始使用 QUIC , QUIC 的协议发现过程是通过识别响应头中的特殊字段来实现

而 Cronet 核心网络引擎完全基于C/C++,所以它除了可以在 Android 中使用之外,也可以通过 FFI 的方式被 Dart 使用,在 Google 产品里, YouTube、 Google App、 Google Photos、 Maps 等都是用 Cronet 来处理网络请求,所以总的来说,Cronet 还是相对可靠的

所以其实对于 Cronet 而言, Flutter 和 Android 都是大差不差的情况。

Cronet 在 Flutter 得推进主要是依赖 Dart 语言的发展进程,例如:

  • Dart 2.18 提供了对两个对于 package:http 特定于平台的 http 库的实验性支持:

    • cupertino_http 基于 NSURLSession 的 macOS/iOS 支持。

    • cronet_http 基于 Cronet,Android 上的网络库支持。

  • Dart 3.2

    • 改进 package:jnigen 实现 Java 和 Kotlin 的直接调用支持,现在可以将 package:cronet_http(Android Cronet HTTP 客户端的包装器)从手写绑定代码迁移到自动生成的包装器

目前 Flutter 使用 Cronet 可以通过引入 cronet_http 包,新版的 dio 内也实现了对应的 cronet_adapter ,如果你使用了 dio ,基本就可以直接使用 Cronet。

对于 Cronet 的使用,也可以分为 使用Google Play 支持版本和使用嵌入式 Cronet 支持版本

  • 如果你的 App 使用 GP 服务,那么其实可以不额外植入 Cronet 依赖,这样的好处就是 Cronet 的更新迭代完全和你的 App 没有关系,升级维护完全交给 GP 负责,相对体积也会小很多。

  • 如果你不使用或者没条件使用 GP 服务,那么也可以使用嵌入式的运行方式,例如 flutter run --dart-define=cronetHttpNoPlay=true

而如果你使用 Dio,那么使用 Cronet 则非常“简单”,只需要一行配置即可完成,不过目前来说,Cronet 只会在 Android 生效,在 iOS 上 NativeAdapter 使用的是基于 NSURLSessioncupertino_http

final dioClient = Dio();
dioClient.httpClientAdapter = NativeAdapter();

为什么 iOS 使用 NSURLSession ?因为 iOS 15 和 macOS Monterey 默认就启用适配了 HTTP/3

最后

本篇主要还是基于科普性质居多,核心还是简单的告诉大家,什么是 HTTP/3 和 QUIC ,QUIC 和 TCP 的区别和优势,最后是 Cronet 的介绍已经如何在 Flutter 里使用 QUIC。

目前基本云厂商都已经支持了 QUIC 配置,所以如果你还没开始接触 HTTP/3 ,现在也许是时候可以试试了,不过我认为,其实也许你的项目已经在使用 HTTP/3 ,只是你还没发现而已。

参考资料:

  • https://unsuitable001.medium.com/package-cronet-an-http-dart-flutter-package-with-dart-ffi-84f9b69c8a24

  • https://www.smashingmagazine.com/2021/08/http3-core-concepts-part1/

  • https://calendar.perfplanet.com/2020/head-of-line-blocking-in-quic-and-http-3-the-details/

  • https://pub.dev/packages/cronet_http

  • https://www.youtube.com/watch?v=YWiRef3wOYY

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

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

相关文章

van-uploader 在app内嵌的webview中的一些坑

问题: 部分版本在ios 中没有问题,但是安卓中不触发图片选择和拍照(之前是可以的,可能是没有锁定版本,重新发版导致的)。在ios中下拉文案是英文,html配置lang等于 zh 也没有用,ios里…

强化网络安全防线,您的等级保护措施到位了吗?

在这个信息化飞速发展的时代,网络安全已经成为我们每个人都需要关注的问题。无论是企业还是个人,我们的工作和生活都越来越依赖于网络。确保网络环境的安全,防止信息泄露和网络攻击,已经成为了一项至关重要的任务。等级保护制度作…

Oracle 正则,开窗,行列转换

1.开窗函数 基本上在查询结果上添加窗口列 1.1 聚合函数开窗 基本格式: ..... 函数() over([partition by 分组列,...][order by 排序列 desc|asc][定位框架]) 1,partition by 字段 相当于group by 字段 起到分组作用2,order by 字段 即根据某个字段…

​面试经典150题——对称二叉树

1. 题目描述 2. 题目分析与解析 2.1 思路一——递归 为了解决问题“检查一个二叉树是否是对称的”,我们需要判断树的左子树和右子树是否是彼此的镜像。这意味着树的左子树的左侧应该与右子树的右侧相同,左子树的右侧应该与右子树的左侧相同。 定义问题…

基于springboot实现人口老龄化社区服务与管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现人口老龄化社区服务与管理系统演示 摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了人口老龄化社区服务与管理平台的开发全过程。通过分析人口老龄化社区服务与管理平台方面的不足&#xff…

Gitee和Git学习笔记

Gitee和Git指令 Gitee提交代码方法1 先将仓库clone到本地,修改后再push到 Gitee 的仓库方法2 本地初始化一个仓库,设置远程仓库地址后再做push 切换分支下载代码通过git clone克隆仓库通过下载 ZIP 的方式下载代码 Git提交指令 解决本地库同时关联GitHub…

货币保卫战,美联储降息预期推迟,油价飙升110美元,亚洲市场股债汇三杀,各国央行操作难度上升!

货币保卫激战 美联储降息预期一降再降,叠加中东局势变化带来避险需求飙升,美元连续第五天上涨之际,新兴市场再次打响“货币保卫战”,而更大的风险似乎仍未过去。亚洲市场普跌,日股跌近2%,韩国股指跌超2%&a…

【好书推荐6】《Excel函数与公式应用大全for Excel 365 Excel 2021》

【好书推荐6】《Excel函数与公式应用大全for Excel 365 & Excel 2021》 写在最前面《Excel函数与公式应用大全for Excel 365 & Excel 2021》关键点内容简介作者简介前言/序言目录 🌈你好呀!我是 是Yu欸 🌌 2024每日百字篆刻时光&…

新手怎么做好抖音小店?这六点是做店的根本,新手商家做店必读

大家好,我是电商花花。 只要我们开通抖音小店,且缴纳好类目保证金,就可以正常选品,上架商品进行售卖了。 如果你是刚开通抖音小店,想要做好抖音小店,下面这几点,一定要注意看。 一、开通精选联…

低版本Oracle客户端或者CMD连接Oracle 12c数据库报错ORA-1017 ORA-12560

exp test_user/test_user123456jgzh fileC:\jgzh.dmp owner(msagx) compressy; exp test_user/test_user123456jgzh fileD:\jgzh.dmp tables(msagx.C_CB_STUDENT,msagx.C_CB_SUBJECT) feedback10000 compressy;

残差网络理解

看了知乎的一篇关于残差网络的文章,https://zhuanlan.zhihu.com/p/72679537,我想发表一点我自己的看法! 1.我对残差网络的理解 残差网络(ResNet)确实与传统的卷积神经网络(CNN)在结构上有所不同…

Qwen1.5大语言模型微调实践

在人工智能领域,大语言模型(Large Language Model,LLM)的兴起和广泛应用,为自然语言处理(NLP)带来了前所未有的变革。Qwen1.5大语言模型作为其中的佼佼者,不仅拥有强大的语言生成和理…

冯诺依曼与进程【Linux】

文章目录 冯诺依曼体系结构(从硬件的角度描述)冯诺依曼体系结构(从软件的角度描述)操作系统(软件)理解管理系统调用和库函数进程查看进程的两种方式 通过系统调用获取进程的PID和PPID通过系统调用创建进程-…

解决Error (169281)、Error (169282)报错问题,QuartusII设置Virtual Pin虚拟管脚的详细操作方法

解决Error(169281)、Error(169282)报错问题,QuartusII设置Virtual Pin虚拟管脚的详细操作方法 1,QuartusII报错信息2,解决办法3,重新编译,成功参考文献: 1,Quartus如何设置虚拟管脚Virtual Pin(具体设置方法) 1,QuartusII报错信息 报错原因:    为了验证FPGA工…

Nginx内存池相关源码剖析(三)小块内存分配逻辑

在Nginx中,小块内存通常指的是那些大小相对较小、分配和释放频率较高的内存块。这些内存块由于数量众多、管理复杂,因此需要使用一种高效的内存管理机制来减少内存管理的开销和内存碎片的产生。 Nginx内存池通过一种预分配和复用的方式来管理小块内存。当…

1688店铺商品接口全攻略:一键获取商品信息,轻松玩转电商数据!

1688店铺所有商品接口技术详解 一、引言 随着电子商务的快速发展,越来越多的商家选择通过1688平台开展业务。为了方便商家获取店铺内所有商品的信息,1688平台提供了相应的API接口。本文将详细介绍如何使用这些接口获取店铺所有商品的信息,以…

Learn something about front end——颜色

​ 好装的标题啊哈哈哈哈哈哈 最近get了一个学习前端的网站叫FreeCodeCamp 原色:rgb三个值的其中一个值拉满,比如说rgb(255,0,0)是红色这样,三个主色: 红色 rgb(255, 0, 0) #FF0000绿色 rgb(0, 255, 0) #00FF00蓝色 rgb(0, 0, …

记录-海思开发板的 嵌入式nginx和 php的移植(交叉编译环境配置)

嵌入式 lnmp搭建的记录 N:NginxP:php编译PHP可能遇到的问题configure阶段:Makefile-make阶段:Makefile-make install阶段: 文章比较水,并没有没解决什么实际问题,有点不好意思发布。但好像又记录…

网工交换技术基础——VLAN原理

1、VLAN的概念: VLAN(Virtual LAN),翻译成中文是“虚拟局域网”。LAN可以是由少数几台家用计算机构成的网络,也可以是数以百计的计算机构成的企业网络。VLAN所指的LAN特指使用路由器分割的网络——也就是广播域。 2、VLAN的主要作用&#xf…

【网站项目】学生选课系统小程序

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…