Quic-Bench
QUIC 为 Google 于 2013 年开发的基于 UDP 的多路并发传输协议,主要优势在于减少 TCP 三次握手及 TLS 握手,同时因为 UDP 特性在高丢包环境下依旧能正常工作。在使用情景复杂的移动网络环境下能有效降低延时以及提高请求成功率。(https://www.chromium.org/quic)
Advantages
- 减少握手次数,TCP 本身需要三次握手,TLS1.1 需要 3 次,TLS1.2,需要 1-2 次,TLS1.3 才能达到 0RTT,而 QUIC 协议层只需要 1-2 RTT,而再次连接为 0RTT;
- 网络抖动时,TCP 会产生阻塞,同时无法多路复用,而 QUIC 流与流之间是独立的,丢包后不会互相影响;
- TCP 协议需要设备支持,比如当前主流移动设备均不支持 TLS1.3,老设备甚至不支持 TLS1.2,QUIC 可以单独不是,升级及兼容更方便。
Bench
此处选择 Android 作为测试平台,对同时提供 QUIC 和 HTTP2.0 支持的腾讯云 CDN 图片进行下载测试。
Server(CDN)
"https://stgwhttp2.kof.qq.com/1.jpg",
"https://stgwhttp2.kof.qq.com/2.jpg",
"https://stgwhttp2.kof.qq.com/3.jpg",
"https://stgwhttp2.kof.qq.com/4.jpg",
"https://stgwhttp2.kof.qq.com/5.jpg",
"https://stgwhttp2.kof.qq.com/6.jpg",
"https://stgwhttp2.kof.qq.com/7.jpg",
"https://stgwhttp2.kof.qq.com/8.jpg",
"https://stgwhttp2.kof.qq.com/01.jpg",
"https://stgwhttp2.kof.qq.com/02.jpg",
"https://stgwhttp2.kof.qq.com/03.jpg",
"https://stgwhttp2.kof.qq.com/04.jpg",
"https://stgwhttp2.kof.qq.com/05.jpg",
"https://stgwhttp2.kof.qq.com/06.jpg",
"https://stgwhttp2.kof.qq.com/07.jpg",
"https://stgwhttp2.kof.qq.com/08.jpg"
Platform:Android
Android 平台上,我们使用从Chromium
中抽取的cornet作为 QUIC Client,对比OKHttp
作为 Http2.0 Client。为了避免 OKHttp 本身优化的问题,我们为 QUIC 提供了 hook OKHttp 用的Interceptor
,此数数据均为 QUIC over OKHttp 的测试结果。直接使用 cornet engine 的测试结果大家可以自行运行。
测试环境:
Phone: 小米 MIX2
OS: Android 8.0 (MIUI9)
Server: caddy 0.9.4
网络请求测试
参考泰国网络调研数据进行测试 (调研数据中无丢包数据)
(以下数据图标,x 轴为丢包率,y 轴为 16 张图下载总耗时,单位 ms,数值越小越好) source: https://docs.google.com/spreadsheets/d/12YcL4e60fvDVliTEzew-c2bbRahBUEaB5HZHQDsPHH4/edit?usp=sharing
BatWifi-Guest (公共 Wifi)
此为高延时的网络情况
(Download 5.7Mbps; Upload 2.8Mbps; Ping 466ms (delay 200ms))
Dtac@地铁
较为正常的 4G 网络
(Download 2.3Mbps; Upload 4.7Mbps; Ping 68ms)
True@地铁
延时稍高的 4G 网络
(Download 6.3Mbps; Upload 9.7Mbps; Ping 123ms)
当丢包率达到 20%以后,HTTP2.0 基本处于超时状态,无法完成测试。
从数据中可以看到,QUIC 和 HTTP2.0 均会明显受到丢包率和延时影响,但两者对 HTTP 的影响程度远大于 QUIC。QUIC 总体性能优于 HTTP,且在高丢包高延时下都能有不错的表现,而 HTTP 则在 15%以上丢包情况下基本处于不可用状态。
Client 性能测试
对比 cornet(和 okhttp 在 CPU、MEM 和 Network 上的表现:
(左 cronet,右 okhttp)
(上下行 1M,0 delay 0 loss)
两者差别不大,同样时间内 QUIC 的带宽利用率明显更高。OKHTTP 在发起请求前,内存和 CPU 会产生一次明显的波动,cornet 反而比较平缓。
不同 loss 下,对比结果差异不大,此处不重复列出。
峰值数据:
protocol | Mem | CPU |
---|---|---|
QUIC | 43.7M | 8.9% |
HTTP2.0 | 45.2M | 10.8% |
Result
从测试结果来看,QUIC 拥有比 HTTP2.0 更好的网络性能,特别是在弱网(高延时、高丢包)下。但因为其基于 UDP,因此在不同 ISP 及不同时段下表现并不稳定,比如在夜间网络高峰期,中国电信对 UDP 有限制,QUIC 表现不如 HTTP,而联通则相差不大,需要在不同国家做更多对比测试,线上也需要有实时监控与动态切换策略。
对于 Client(Android),因为需要单独打包协议 so,对包体积影响较大,未压缩情况下会带来 2M 左右负担。调研了携程等公司的做法,可以采取动态下发,lazy load 的形式。在合适的时机下载 dex 和 so 进行加载,避免对包体积的影响。
在 proguard 下,集成 cronet 会增加 1400 个方法,160k dex(未压缩),so download size 1.5M,可动态加载。
QUICDroid
对 cronet 的封装,支持以 OKHTTP intercepter 方式添加 QUIC 支持,方便无感知接入以及降级控制。
Usage
// init
QUICDroid.init(context, cronetEngine)
// hook with okhttp
OkHttpClient.Builder()
.addInterceptor(QUICInterceptor())
.build()
// enable or disable
QUICDroid.enable = true/false
other cronet config see https://chromium.googlesource.com/chromium/src/+/master/components/cronet/README.md?autodive=0%2F%2F
Warning
因为无法从协议层去判断 Server 是否支持 QUIC,需要 Client 预先使用其他手段判断 Server 对协议的支持再作启用。
Other
QUIC@微博 https://itw01.com/V2WI5ES.html QUIC@腾讯 https://zhuanlan.zhihu.com/p/32560981 QUIC@QZone http://www.infoq.com/cn/news/2017/10/qzone-quic-practise