1. 使用已编译好的 Cronet 库
编译好的 Cronet 可以在 Google cloud上找到。由于数据存储在 Google cloud 上,因此不能直接下载,需要使用 gsutil 工具。这样就可以把预先编译好的 Cronet 库给下载下来。
如果安装好 gsutil 工具后,接下来的步骤是执行 gsutil init 初始化命令,因为墙的关系你大概率会初始化失败。本人亲测,这一步可以跳过。
由于版本比较多,建议选择新版本,点击下载会弹出 gsutil下载命令提示框,此时只要点击复制就好。然后通过终端执行命令下载。
举例:
gsutil -m cp -r \
"gs://chromium-cronet/ios/113.0.5672.0/Debug-iphoneos" \
"gs://chromium-cronet/ios/113.0.5672.0/Debug-m1simulator" \
.
把下载下来的 sdk 放入到项目中,之后你可能还需要额外添加一些系统库的依赖:
- libc++.tbd
- libresolv.tbd
- MobileCoreServices.framework
- SystemConfiguration.framework
- UniformTypeIdentifiers.framework
- Security.framework
- CoreTelephony.framework
Xcode Build settings 里面的 other link flags 添加 -ObjC
当然你也可以把 Cronet.framework 放入到你自己的pods里面。不过制作自己的组件就是另一个话题了。
2. 源码下载
Chromium doc: chromium.googlesource.com/chromium/sr…
chromium.googlesource.com/chromium/sr…
因为对源码编译过程比较复杂,建议直接使用已编译好的 Cronet 方式。
3. 检测制定服务器域名是否支持 HTTP/3 和 QUIC
4. 项目编译运行的一些问题总结:
- 在调用 Cronet SDK 相关方法的时候一定要仔细看注释说明,是在 -(void)start 之前还是之后调用。
4.1 关于 Cronet 日志
原则上是不应该开启的,因为开启记录网络日志会对性能产生影响,而且日志数据比较多。除非在做网络调试解决网络问题。
4.1.1 开启日志的方法和时机
+ (BOOL)startNetLogToFile:(NSString*)fileName logBytes:(BOOL)logBytes; 开启日志记录方法没有说明是在 -(void)start 之前还是只有调用。但是根据我测试的结果,只有在-(void)start 方法调用之后开启返回结果才是 YES 在-(void)start 之前会返回 NO
4.1.2 日志目录管理
根据查看Google chromium cronet iOS 源码实现,得出结论如下:
- 日志文件和指定保存日志文件的目录需要在本地沙盒的 Documents 目录下面提前创建好。
- 在调用
startNetLogToFile: fileName方法时,fileName 应该传入 Documents 后面的路径无需以"/"开头。举例说明: -
- 在
....../Documents/cronetLogs/netlog1.log目录下生成了netlog1.log日志文件,调用startNetLogToFile:传入fileName时应该传入"cronetLogs/netlog1.log"因为startNetLogToFile:内部会去把Documents和fileName拼接起来使用。所以也不要传入完整的绝对路径.
- 在
4.2 日志管理
- 日志文件内容非常多,如果要在本地保存太多会非常消耗磁盘空间。可考虑采用 LRU 策略管理日志。
- 鉴于 netlog 内容比较多,网络请求和日志最好建立映射关系,即一个请求对应一个日志文件目录,目录名可以是请求地址的 hash 值。因为一个请求可能发起多次,日志名采用时间戳。
4.3 日志可视化
netlog-viewer.appspot.com/#import
日志后缀最好使用 .json 结尾。因为拿到日志文件后直接通过上述连接导入就可以可视化查看了。
5. Cronet 支持的网络协议
Cronet 内部支持多种协议比如:QUIC,HTTP 等。我们比较关心 Cronet 在他们之间是如何进行升降级的?
5.1 Cronet 自身生降级策略
服务发现
通过 Cronet 访问普通 HTTP 请求,如果在 Response Header 添加支持 QUIC 协议的标识: alt-svc: quic=":443"; ma=2592000; v="43,46", h3-Q043=":443"; ma=2592000, h3-Q046=":443"; ma=2592000, h3-Q050=":443"; ma=2592000, h3-25=":443"; ma=2592000, h3-27=":443"; ma=2592000 来告知客户端,服务端支持 QUIC。Cronet 在下次发起请求就会在 HTTP 和 QUIC 之间进行一次竞速。来确定后续请求走何种协议通信。
QUIC 和 HTTP 之间的竞速
当客户端 Cronet SDK 已经知晓了服务端支持 QUIC 协议(不管是一开始就知晓服务端支持,还是通过服务发现知晓) Cronet 在接下来得请求都会通过一次竞速机制来确定后续请求采用哪种协议。竞速策略如下:
- Cronet 同时发出基于 TCP 的 HTTP 连接和基于 UDP 的 QUIC 连接
- Server 接收到两种连接后均会反馈给客户端
- 客户端等待两种连接响应,按照时间维度,判断哪种连接首先建立成功。
- 如果 QUIC 连接首先完成,以后的连接都走 QUIC 协议通信
- 如果 HTTP 连接首先完成,后续的请求直接按照 HTTP 协议通信
- 整个过程可以通过 Wireshark 抓包看到
QUIC 通道复用策略
Cronet 内部会建立连接池,来管理已经建立的 QUIC 连接以便实现连接的复用。WI-FI 和 4/5G 切换的情况下 Cronet 会尝试通过连接池恢复连接来减少连接建立的时间和延迟。
6. 如何支持 HTTP DNS
先挖个坑,后续更新