HTTP/2其实出来已经很长时间了,但是一个新的协议,新的标准从出现到大量被采用,总是会经历一个过程。我们的产品最近基于网络请求优化的要求,需要将之前的HTTP/1都升级到支持HTTP/2,这个事情其实需要两方同时进行,服务端和客服端需要同时支持HTT/2。在做这个事情之前需要首先调研HTTP/2,了解它的特性和优缺点。
对HTTP2的基本的调研结果如下:
HTTP/2的由来
HTTP/2 的前身是 SPDY协议,第一版草稿就是基于 SPDY3 规范修改制定而来。HTTP/2维持了原来 HTTP 的范式(不改动 HTTP/1.x 的语义、方法、状态码、URI 以及首部字段等等)
为什么是HTTP/2
-
连接次数减少 理想情况下,单个域名对应一条链接,如果此链接一直保持有数据传输,则类似一个长链接,不会建立多条链接,HTTP/1.1虽然也可以通过keep-alive做到类似的效果,但是无法做到请求并发,这也是HTTP/2不同于HTTP/1.x的一个重要方面
-
并发发送请求 发送请求不再是串行, 提高了发送效率,同一时间可同时发出多个请求。
-
流量节省 由于 HTTP/2的发送协议的修改和优化,流量的表现也有明显提升。
HTTP/2的特性
-
二进制分帧 HTTP/2 在维持原有 HTTP 范式的前提下,实现突破性能限制,改进传输性能,实现低延迟和高吞吐量的其中一个关键是:在应用层(HTTP2)和传输层(TCP or UDP)之间增加了二进制分帧层
-
多路复用
- 同一个流中的帧是交错传输的!
- Header 帧必须在 data 帧前面,因为无论是客户端还是服务端,都依赖 header 帧的信息解析 data 帧的数据!
- 先到的帧不一定先返回,快的可以先返回!
-
头压缩
通过HPACK 压缩算法,HTTP2 在户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送;通信期间几乎不会改变的通用键-值对(用户代理、可接受的媒体类型,等等)只需发送一次
-
服务器推送
-
送优先级与依赖性
-
可重置
-
流量控制
-
HTTPS RFC 规范并没有要求 HTTP2 强制使用 TLS,但是目前世界所有浏览器和服务器实现都基于 HTTPS 来实现 HTTP/2
以上是在支持HTTP/2前所做的一些调研,一些HTTP/2的特性,略显简略,因为此文的重点并不是介绍协议特性,因此就不赘述了。接下我想具体谈谈我们在支持HTTP/2的过程中所做的事,所遇到的问题和解决方法。
在现有工程支持HTTP/2
-
使用大名鼎鼎的OkHttp来替换原有使用HttpURLConnection封装的网络基础模块,因为OkHttp原生支持HTTP/2,实际上我们不需要自己去实现HTTP/2协议,更不需要去设计和管理复杂的网络基础设施。
-
对现有代码逻辑的兼容
因为现有代码中很多不那么规范的写法,例如文件上传,将参数拼接和文件内容的字节流写在了一起,这类网络请求本来也不是HTTP/2的优势场景,因此还是走HTTP/1.x协议,因此我们设计了一个网络请求协议分派的管理类,在这个类里面统一做网络请求协议的分发。这样做的另一个考量是如果支持HTTP/2协议的这个版本在上线后出现大面积问题的话,可以迅速再切回HTTP/1.x。
- 加入顺延心跳
HTTP/2的理想情况下有点类似长连接,但是毕竟不是长连接,在一定的时间段如果没有请求的话,连接一样会断开,因为我们App的大部分业务请求其实都对应一个域名,所以保持这条连接一直不断就变得比较有意义,所有我们加入了心跳机制,心跳间隔以顺延的方式,进一步减少不必要的心跳,这样一来既不会有过多的心跳,也保证了连接不会频繁断开。
- DNS 优化
这个在上一篇讨论连通性的文章中已经讨论过了,这里就不再详述。
如何衡量HTTP/2带来的提升
有的时候衡量你做的事的结果比起做事本省可能还要难,这次支持HTTP/2和优化连通性的工作就属于此类,做本身真不是很难,可预见的问题也都在可控范围之内,但是要衡量它的效果,或者说带来的提升和优化,这就需要设计一整套的衡量指标了,并且这些指标也都需要在这个支持HTTP/2的版本上线前就准备好。为此,我们也是调研了很多资料,结合我们能通过上报的数据,最终定下了如下几个指标来衡量:
- RTT - 完成整个事件的时间
这个数据我们为了和没有支持HTTP/2的版本作比较,将上报的数据做了分区间整理,也就是将耗时从<200ms, 200~500ms, 500~700ms, 700~1000ms, >1000ms做了五个区间来统计每个区间的请求数在总请求数中的占比,通过两个版本的数据来验证HTTP/2的优化和提升,这个指标是最直观的。为了避免一些脏数据导致的数据偏差,我们还针对单个接口进行了数据分析。
- 请求失败率
这个比率是有所下降的,尤其UnknownHostException异常导致的失败在总失败中所占比重明显下降,这个数据的提升得益于上篇文章中对连通性的优化。
- 请求各个阶段的耗时
这个数据做了上报和统计,但是并没有去细致的分析各个阶段的耗时,不过的确可以作为一个参考。
- 观察并发请求下的表现
因为我们做的是直播业务,在进入直播间的一瞬间,可能会有非常多的并发请求,这种场景就体现出了HTTP/2并发发送请求的特性,可以说提升非常可观。
如何测试HTTP/2
如果在有限的资源条件下测试和验证HTTP/2,可能最先想到的就是要进行弱网环境测试:
如何进行弱网测试:
-
SIM卡的网络切换,手机-设置-移动网络设置-网络类型选择3G,4G卡都可以设置关闭3G/4G,只走2G网络
-
使用虚拟机模拟网络速度,如用树莓派搭建的弱网测试仪
-
使用软件进行网络代理,模拟不同的网络带宽、延时率、丢包率
- Charles
- Chrome的webview调试工具
- iOS自带Network Linker Conditioner
以上就是我们在支持HTTP/2过程中的一些调研结果和实际工作中的经验总结。