HTTP/2正给Web性能最佳实践带来怎样的影响?

gynh 8年前

来自: http://developer.51cto.com/art/201602/505775.htm

超文本传输协议(简称HTTP)可谓万维网与网络空间的建立基础。虽然HTTP早已有些过时,但作为该协议中使用面最广的版本,HTTP 1.1已经快20岁了——这让我们不得不赞一句“老当益壮”。在其于1997年刚刚得到批准时,软盘驱动器与调制解调器还是当时PC设备的必备周边,而Java也仅仅是一款表现出良好发展前景的新生编程语言。而到2015年5月,HTTP/2正式亮相并致力于解决HTTP 1.1在现代网络时代下无法应对的某些性能难题。过去一年以来,对HTTP/2的支持已经或者即将广泛出现在浏览器、Web服务器、商用代理以及各主要内容交付网络当中。

遗憾的是,对于负责编写Web代码的开发人员而言,HTTP/2过渡工作并不那么直观,而其对于处理速度的提升也绝不会自行出现。这款新型协议在面对高性能Web应用以及多种尚无法为其提供支持的现有工具——例如调试代理——时不断挑战着程序员们的脑力与技能水平。在今天的文章中,我们将介绍HTTP/2的基本概念及其如何改变Web性能之最佳实践。

二进制帧:HTTP/2的“基本单位”

HTTP 1.1的一大优势(至少相较于非安全连接而言)在于其支持在端口80的telnet会话中利用文本与Web服务器进行交互:输入GET / HTTP/1.1能够在大多数Web服务器上返回一个HTML文档。由于这是一项文本协议,因此其调试流程相对比较直观。

相对于1.1版本的文本,HTTP/2中的请求与响应则通过二进制帧流的形式表现,我们将其称为HTTP/2 RFC中的“基本协议单位”。每一帧都拥有自己的类型,旨在实现不同作用。HTTP/2的作者们意识到,HTTP 1.1无疑将继续存在(毕竟Gopher协议仍然得到广泛使用)。因此HTTP/2的二进制帧请求需要被映射至HTTP 1.1请求,从而确保其拥有向下兼容能力。

HTTP/2当中还有着其它一些新特性,且无法直接映射至HTTP 1.1。服务器推送(也被称为‘缓存推送’)以及流重置都是利用二进制帧类型实现的新特性。帧同时亦可具备优先级,允许客户端向服务器提供排序思路,从而优先处理一部分资产类别。

除了使用Wireshark 2.0之外,对个别二进制帧进行实际查看的最佳方式之一就是使用谷歌Chome中的net-internals标签(在地址栏中输入chrome://net-internals/#http2)。大型网页的数据往往难于理解。Rebecca Murphey编写出了一款极为实用的工具,从而将其以可视化方式显示在命令行当中。

除此之外,这套用于获取资产的协议还能够被显示在Chrome Web开发者工具当中——右键点击列标题并选定“协议”即可:

在谷歌Chrome开发者工具当中显示协议类型。

在这里列出的全部HTTP/2请求都使用通过传输层安全(简称TLS)机制建立的安全连接。目前各主流浏览器都强制要求HTTP/2以安全形式存在。这种作法有着自己的切实理由:名为应用层协议协商(简称ALPN)的一套TLS扩展允许服务器了解浏览器对HTTP/2(以及其它协议)的支持能力,从而避免进行额外的数据往返。这同时也能够帮助那些无法理解HTTP/2的服务,例如代理——它们只会接收到经过加密的传输数据。

利用多路复用实现延迟削减

HTTP 1.1中的一大核心性能难题在于延迟水平,或者说其耗费在制定请求并接收响应这一流程身上的总体时间。这个问题正随着典型网络页面中图片数量的增加以及JavaScript与CSS元素的不断膨胀而愈发严重。每当获取到一项资产,其往往都需要创建一个新的TCP连接。这种要求主要基于两个理由:每台主机能够同时打开的TCP连接数受到浏览器的限制; 建立新的连接需要承担一定程度的性能损失。如果某台物理Web服务器与用户间距离很远(例如服务器位于新加坡,而用户请求则源自美国东海岸一座数据中心的托管页面),那么等待时间也将相应增加。这样的场景并不罕见——根据最近的一篇报道所言,全球超过70%的互联网流量都需要通过北弗吉尼亚州的数据中心。

HTTP 1.1提供多种不同方案以解决延迟问题,其中包括通道传输与Keep-Alive头。然而,通道传输从而得到广泛采纳,而Keep-Alive头则面临着行头拥堵的困扰:当前请求必须彻底完成后,下一请求才能正确发送。

在HTTP/2当中,单一TCP连接内的多条资产请求能够得到复用。与使用Keep-Alive头的HTTP 1.1请求不同,HTTP/2的各请求与响应二进制帧以交错方式进行,这意味着行头拥堵状况将不复存在。建立连接的成本(也就是人们常说的‘三方握手’)在每台主机上只进行一次。多路复用在安全连接方面拥有尤其突出的表现,这是因为传统的多次TLS协商方案会显著提高性能成本。

在HTTP/2当中,单一主机内的多资产请求只使用单一TCP连接。

Web性能影响:与内联、级联及图像精灵说再见?

HTTP/2多路复用给前端Web开发人员带来了广泛的影响。它消除了多种通过捆绑相关资产以削减连接数量的长期解决思路的存在必要性,具体包括:

  • JavaScript与CSS文件级联: 将多个小型文件汇总成一个大型文件,从而降低总体请求数量。
  • 图像精灵: 将多个小型图像汇总成一个大型图像。
  • 域名碎片: 在多个域之间将静态资产请求进行拆分,从而增加浏览器所能允许的总体开放TCP连接数量。
  • 内联资产: 将资产同HTML文档源进行绑定,包括 base-64编码图片或者直接写入至<script>标签当中的JavaScript代码。

由于资产不再进行绑定,因此我们有机会更为积极地对Web应用程序中的小型片段加以缓存。以下示意图对此做出了原理性阐述:

一个级联指纹验证型CSS文件被解绑为四个较小的指纹验证文件。

常见的级联模式是将样式表文件进行绑定,从而确保单一应用程序内的不同页面被汇总至单一CSS文件之内,旨在降低资产请求数量。这个大型文件随后会通过文件名内的MD5内容散列进行指纹验证,确保其能够由浏览器所主动缓存。遗憾的是,这样的解决方案意味着即使是规模极小的变化——例如网站的可视化布局、字体样式以及标题内容等改变——都要求对整个级联文件进行重新下载。

当小型资产文件接受指纹验证时,相当一部分JavaScript与CSS组件都不会频繁发生内容变更,这就意味着其能够为浏览器所缓存——立足于此,单一功能的小规模重构将不再导致大量JavaScript应用程序代码或者CSS失效。

最后,级联机制的消失能够降低前端构建基础设施复杂性。相较于通过一系列预构建步骤进行级联资产处理,现在我们可以将其作为小型文件直接包含在HTML文档当中。

在真实世界中使用HTTP/2的潜在弊端

HTTP/2带来的各种优化手段同时也意味着各类无法为其提供支持的浏览器可能因此陷入不利局面。相当一部分陈旧浏览器仍然倾向于通过资产绑定以降低连接数量。截至2016年2月,caniuse.com网站报道称,全球浏览器中能够支持HTTP/2的比例为71%。类似于放弃对IE 8.0的支持,接纳HTTP/2或者采取混合方案的决定将给每个站点中的全部相关数据造成影响。

正如此前有博文提到,卡恩工程院曾以其网站上的HTTP/2流量进行分析,并拆分出大量实际上会增加所传输字节总量的资产内容。在使用zlib时,对单一大型文件的压缩效率要远高于压缩大量小型文件。同样的效应对于包含成百上千非绑定资产的HTTP/2站点来说将变得非常突出。

在浏览器中使用HTTP/2还要求我们通过TLS进行资产交付。对于新手们来说,设置TLS证书是个非常繁琐的任务。幸运的是,Let’s Encrypt等开源项目的出现正努力让证书注册工作变得更加便捷。

普及进展

大多数用户并不在乎所访问站点到底使用哪种应用协议——他们只希望获得与预期相符的速度表现与使用体验。尽管距离HTTP/2获得正式批准已经过去了近一年,但希望以其为基础构建更快站点方案的开发人员们仍然在对相关最佳实践进行学习。转移至HTTP/2的具体收益在很大程度上取决于特定网站的实际构成以及其用户使用现代浏览器的确切比例。另外,对新协议的调试也极具挑战性,而目前易于使用的开发者工具也仍然比较有限。

尽管存在这些挑战,HTTP/2的普及态势仍然一路向好。根据研究人员对高人气网络站点的流量扫描,目前各顶级站点中使用HTTP/2的比例正不断提升,特别是在CloudFlare与WordPress相继于2015年年末宣布为HTTP/2提供支持之后。而在考虑进行转移时,最重要的是认真权衡并监控不同环境之下的资产加载与页面加载时间。由于供应商与网络专业人士本身亦处于学习与摸索阶段,因此根据真实用户数据做出决断就显得至关重要。面对网站不断臃肿化的危机,我们现在是时候采取措施,独立于协议之外对资产总量进行削减了。

在本系列HTTP/2文件的第二部分中,我们将着眼于HTTP/2的具体实现案例并探讨如何将其引入大家的服务器乃至调试真实流量。

原文标题: How HTTP/2 Is Changing Web Performance Best Practices

【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】