大厂技术分享:网易新闻 QUIC 敏捷实践

通过敏捷快速实践 QUIC ,网易新闻在3个月内,将端内 QUIC 请求占比提升到 75%+,如 图1 所示,并将客户端请求平均响应时间 RT 降低了 45%,请求错误率降低了 50%+,视频卡顿率降低了 25%+ 。

大厂技术分享:网易新闻 QUIC 敏捷实践

文章插图
图1 客户端 QUIC 请求占比
(黄色部分为 QUIC 请求,蓝色部分为其他协议请求)
如何做到以最小的成本、最小的风险和最大的收益接入 QUIC,是本文讨论的核心 。
什么是QUIC?QUIC 是 Quick UDP Internet Connections 的缩写,意为“快速 UDP 网络连接” 。QUIC 由 google 实现于2013年,是一种网络传输协议,旨在提升网络传输速度 。2015年,QUIC 被提交到 IETF,目标是成为下一代的正式网络规范,2018年,HTTP over QUIC 被 IETF 重命名为 HTTP/3 。
在 UDP 之上,QUIC 实现了类似 TCP 的丢失重传机制,QUIC 传输以数据包级报头发送,并对每个包增加了单调递增的数据包号来代表传输顺序,当检测到必要帧丢失时,QUIC 会将必要帧绑定到新数据包重发 。QUIC 对报文头部和数据也都进行了加密,且建联时改进使用了 DH 密钥交换算法,在防劫持方面也具有一定优势 。
所以,QUIC 虽然基于 UDP 实现,但在功能上等价于 TCP + TLS + HTTP/2,除此之外,相较于传统的 HTTP + TCP,QUIC 还具有多项改进网络传输的优势,其部分优势如 图2 所示 。
大厂技术分享:网易新闻 QUIC 敏捷实践

文章插图
图2 QUIC表现优势
QUIC 目前分为 gQUIC 与 iQUIC 两种,gQUIC 即为最初的 Google QUIC,而 iQUIC 是后来 IETF 制定的通用传输协议,如 图3 所示 。
大厂技术分享:网易新闻 QUIC 敏捷实践

文章插图
图3 QUIC分类
相较 iQUIC 而言,gQUIC 目前的应用较为普遍、成熟,如 Cadddy 支持 gQUIC,客户端还有 Chromium 的 Net 库 Cronet 也可以支持 gQUIC,包括 ExoPlayer 等三方库也都提供了对于 gQUIC 的扩展支持 。目前来看,选择 gQUIC 对于渴望改善网络传输情况的开发者来说,在接入成本和接入效率上具有优势 。
QUIC 接入策略为了快速接入并验证 QUIC,在流量入口设计上,我们选择用 Nginx + Caddy 方案实现;在客户端网络库上,我们选择了 Chromium 的网络库 Cronet,原因如下:
  • Google 对 Chromium 开源多年,已经过众多软件团队的验证,基础功能稳定良好;
  • 作为 Chromium 的网络库,Cronet 的跨平台性良好,在 Android 和 IOS 双端可可直接接入;
  • gQUIC 相比 iQUIC,在各方面支持都更成熟,Cronet 也可以直接支持 gQUIC;
2.1 流量入口
流量入口设计上,由 Nginx 负责处理 HTTP 请求,Caddy 负责处理 UDP 请求,如 图4 所示 。
大厂技术分享:网易新闻 QUIC 敏捷实践

文章插图
图4 流量入口设计
2.2 网络库方案设计
在客户端网络库处理上,如何能保证侵入性最小,风险性最低,并最快接入 QUIC,以验证线上收益,成为了项目的主要目标 。
由于客户端用户规模较大,一些量级较小的第三方 QUIC 处理库使用存在一定风险性问题,而自研 QUIC 库支持的成本和效率远远达不到预期,且 QUIC 的网络改善收益对于 Team 来说是未知的,选择一款稳定可靠的网络库来快速达到 MVP(最小可行性) 是首要目标,所以在 Android 和 iOS 端,我们都选择了使用 Cronet 。
2.2.1 Android
Android 端目前使用的网络库是 OKHttp,为了更清晰有效地验证 QUIC 的效果,我们在接入 Cronet 的同时,也保持了原有网络库 OKHttp 处理逻辑的不变,通过动态配置控制 AB 策略 。上线后通过逐渐切量,一部分网络请求走 Cronet,一部分网络请求走 OKHttp,以清晰对比出二者的差异 。
而端内目前的两套数据上报机制,一种基于 OKHttp 事件监听实现,一种通过 Hook OKHttp 的事件监听实现,而 Cronet 的上报与 OKHttp 事件回调可以对齐统一,可维护性良好,再次增加了我们选择 Cronet 的理由 。
2.2.2 iOS
Cronet 在 iOS 接入方面,API 设计友好,基于 NSURLProtocol 通过网络拦截即可实现 。iOS 的接入流程可以简单分为初始化 Cronet 和注册 NSURLProtocol 协议两个部分 。
2.3 网络库接入
2.3.1 Android
在接入 QUIC 时,Android 使用网络库 OKHttp 的拦截器(Intercept)机制来处理网络请求较为便捷,当网络请求从业务顶层通过 OKHttp 传输到 Cronet 对应的拦截器时,会交由 Cronet 处理 。
2.3.1.1 拦截器处理
OKHttp 拦截器(Intercept)设计基于责任链模式,由于在拦截器中接入 Cronet 后,网络请求会被 Cronet 库拦截处理,造成后续的拦截器短路,中断 Request 与 Response 信息在拦截器中的传递,所以 Cronet 的拦截处理就应尽量下沉,置于顶层应用拦截器的最底部,如 图5 所示 。


推荐阅读