写点什么

HTTP/2 的应用实战:每天 400gb 图片

2016 年 8 月 10 日

This is a repost of “ Real–world HTTP/2: 400gb of images per day ” from the 99designs Tech Blog. (本文译自 99designs 技术博客“ Real–world HTTP/2: 400gb of images per day ”一文。)

终于正式确定了的 HTTP/2 规范逐渐吸引了广大 Web 性能社区的注意。这一新协议意在解决古老的 HTTP/1.x 协议中有关网络性能的常见问题,同时保留了老协议所用的语义。

我们于今年初开始为小范围的静态资产运用了这一全新协议。通过成功构建全新基础结构建立信心,我们开始将所有静态资产过渡至 HTTP/2。令人吃惊的是,平台上部分内容的性能不升反降。本文将对我们采用 HTTP/2 过程中遇到的性能退化问题进行深入研究。

我们的经验并非解决所有 HTTP/2 性能问题的万灵药,希望通过分享可以为大家带来启发。

为何选择 HTTP/2?

无论怎样,一提到 HTTP/2 很多人冒出的第一个念头就是性能的大跃进,为什么说我们有关 Web 性能的理解都是错误的?

实际上性能只是 HTTP/2 的差别之一。

与 HTTP/1.x 为每个资源建立新连接的做法不同,HTTP/2 最多只为每个主机名建立一个连接。这个连接是一种通过二进制分帧协议(Binary framing protocol)建立的多路传输流(Multiplexed stream),由二进制分帧负责对不同资源的并发请求进行匹配。

来自 Ilya Grigorik 演讲“HTTP/2 已来,一起优化吧!”的一页幻灯片

由于不再受制于每个连接只能执行一个事务,头端阻塞(Head-of-line blocking)的情况有了大幅改善。所需创建的连接数量更少,这也意味着对延迟和TCP 拥塞控制的敏感度大幅降低。通过配合使用,这些特性可显著改善性能,因为可大幅减少服务器和客户端之间来回往返通信的数量和所需时间。

监控HTTP/2 的性能

我们使用 Calibre 对最终用户的性能进行全面监控并收集各种度量指标,同时用非常醒目的 Geckoboard 将部分数据显示在办公室里。

墨尔本办公室中受到 Etsy 启发开发的性能仪表盘

我们使用下列度量指标代表用户感知的页面加载性能和 HTTP/2 表现。使用这些指标是因为它们会受到页面加载生命周期内不同因素的影响。

  • DOMContentLoaded 事件可代表异步脚本的延迟。
  • 首次绘制所需的时间是指诸如 CSS 和字体等影响渲染的资源所导致的延迟。
  • 彻底完成视觉呈现所需的时间是指诸如图像和可能的异步脚本等不影响渲染的资源所导致的延迟。
  • 速度指数代表一段时间内彻底完成视觉呈现的速率。

测试并确认 HTTP/2 的成功实现

我们首先将图片缩略图的 CDN 换为 CloudFlare,该服务内建支持 HTTP/2。最初进行的性能评测显示 CloudFlare 的延迟和响应时间与我们原有的 CDN 不相上下。

作为一种设计作品的商店,我们的大部分页面都以图片为主,通常一个页面会包含超过 50 张图片。

包含很多小资源的页面反而容易受到 HTTP/1.x 连接延迟小幅变化的影响。对于这种延迟变化幅度很大的页面,我们的预期是能尽可能快速地完成视觉呈现工作。具体能快多少取决于连接延迟和图片数量,我们原本认为在高延迟低带宽的 3G 连接下依然会存在这种情况。

对于带宽要求高的页面,没指望能实现较大程度的改善。

单独为图片启用 HTTP/2 并不能缓解头端阻塞的情况,因此也没指望首次绘制或DOMContentLoaded指标能够有所改善。

实际情况

最终获得的结果并不是非常明了。下文将探讨在推行 HTTP/2 过程中遇到的一些差异和惊喜,以及未来的计划。

测试

我们通过一项功能标记启用 HTTP/2 CDN 后,一周时间里在启用或不启用新 CDN 的情况下抓取了大约 100 个 Calibre 截图。Calibre 的 Chrome 代理程序位于美国,使用了低延迟高带宽连接。

案例研究:设计师作品集

99designs 网站的设计师作品集通常是受延迟影响十分严重的页面。我们发现速度指数和彻底完成视觉呈现所需的时间有了 5% 的提高。

首次绘制所需时间也有相应提高,但有趣的是首次渲染使用 HTTP/2 时更为完整。

通过 HTTP/2 提供图片时的首次渲染更完整

案例研究:Discover 作品库

我们的 Discover 作品库是整个平台中最极端的应用。每个页面包含总大小约 10mb 共 80 张图片,这些页面对带宽要求极高,因此延迟降低所实现的改善实在是微不足道。我们原本也没指望这方面的性能会有太大变化。

但实际发现在完整视觉呈现和速度指数方面平均性能反而有 5%~10% 的退化。然而总的来说页面加载时间减少了,这意味着我们已经从连接延迟的降低中获益。

HTTP/2 首次绘制的延迟和完整视觉呈现所需的时间

高延迟测试

为了收集有关高延迟连接的数据,我们在 3G 网络环境下使用了 WebPagetest

首次绘制依然显得更完整,但用的时间略微长了些。整体页面加载依然会提前进行。

让人没想到的是,完整视觉呈现的延迟竟然进一步增加了,设计师作品集平均增加 15%,Discover 作品库平均增加了 25%。

长话短说

对于一个包含大量图片,对延迟要求较高的典型页面,使用高速低延迟连接的情况下完整可视呈现的平均速度提高了 5%。

对于包含极多图片,对带宽要求较高的页面,使用同一条连接的情况下完整可视化呈现的平均速度降低了 5%~10%。

在高延迟低速连接情况下,我们发现页面完成视觉呈现的过程产生了较大延迟。

所有测试中都发现页面整体加载时间有改善,并且首次绘制也更为完整。

事后分析

收集到的数据为我们提出了一个大问题:

在使用 HTTP/2 时尽管加载速度更快,但对带宽要求高的页面用了更长时间才完成视觉呈现。为什么?

猜测 1:网络饱和

由于需要开放大量短暂连接,HTTP/1.x 流量有着“突发(Bursty)”的本质。在一些开发工具的网络瀑布图中可以明显看到这种现象。

HTTP/1.x 参差的网络瀑布

最初我们认为用一个更“长寿”的 TCP 连接加载数 MB 图片数据可能会彻底耗尽带宽,致使浏览器无法加载决定页面布局所需的资源,例如 CSS、JS 和字体。

然而在加载影响页面布局的资源时看到的网络瀑布图中并没有延续这样的情况。

猜测 2:加载优先级的变化

在使用 HTTP/1.x 时,浏览器受到限制针对同一个“源”最多只能维持大约 6 个并发的开放连接。随着更多资源逐渐被发现,浏览器会将其加入先进先出(FIFO)资源下载队列。对同一个源所创建的开放连接进行这样的限制,实际上等于为资源的加载划分了优先级。

加入队列的每个资源请求都代表一个浏览器与源之间的往返“请求 - 响应”过程,必须首先完成这一过程才能让资源退出队列。这一行为也就是我们所说的网络瀑布。

HTTP/2 的分帧协议使得浏览器能够将多个请求和响应“缝合”在一起,因此不再有队列文档优先级顺序这一概念。

Discover 作品库页面在 HTTP/1.x 和 HTTP/2 环境下的网络时间线

HTTP/1.x 时代将<script>放在文档末尾的这个最佳实践现在开始起到了反作用。

我们有关性能的认识真的都错了吗?

然而DOMContentLoaded的速度又推翻了这一理论。通过网络瀑布图可以确认决定页面布局的资源其处理优先级远高于图片。

实际上浏览器下载队列中的资源依然存在优先级的差异。也正是因此,先为 80 张图片发出请求随后才发现页面底部的<script>,这个顺序没有造成脚本加载的延迟。

资源的实际加载行为并无公开记录,没有特别指定,并且还会时常变化。就算不是所有浏览器,但大部分浏览器都会先于图片处理 CSS、JavaScript 和字体。

猜想 3:传输流

由于取消了 HTTP/1.x 中并发连接的限制,浏览器可以更自由地同时加载这 80 张图片。服务器也会同时对这些针对图片的请求做出响应,下载完成的图片会立刻显示在浏览器中。我们可以从网络时间线中确认这一行为。

通过 HTTP/2 处理 Discover 作品库页面中前 20 个图片请求时的网络时间线

图片的请求依然会按照预定顺序处理。然而较小的图片可能会更快速下载完成,因此可以更快速渲染出来。如果有较大的图片恰好处于最初的 Viewport 过程中,无疑需要更长时间才能加载,这会导致完整视觉呈现出现延迟。

3G 网络情况下使用 HTTP/1.x 和 HTTP/2 加载 Discover 作品库页面过程对比

同时这也解释了为什么在带宽严重不足的情况下完整视觉呈现用了更长时间,并存在如此大的变化。

HTTP/2 的一些注意事项

我们在传输流方面遇到的这种问题实际上是 HTTP/2 中一个尚未被太多人关注的重大功能。

Ilya Grigorik 对此有一个很棒的描述:

“使用 HTTP/2 的情况下,将由服务器决定浏览器获得响应数据的最佳方式。

和字节数无关,和每秒请求数也没关系,重点在于交付数据的顺序。你的 HTTP/2 服务器一定要进行慎重的测试。”

传统方式下会按照预定顺序请求不同资源,不过为了改善性能,浏览器可能会酌情进行一些调整。这种方法就造成了一个大问题:

  • 具体的调整不公开
  • 不同浏览器的调整也不相同
  • 同一浏览器的不同版本调整也不同
  • 这种调整通常会适用于所有网站

这些调整中所产生的变化可能导致页面加载性能在没有事先通知的情况下突然发生变化。

HTTP/2 彻底改变了资源优先级的处理方法,现在可由浏览器和服务器共同决定优先级。浏览器向服务器提出自己的优先级建议,但最终还是由服务器决定优先处理哪些内容。

这种“权力”的变化是一把双刃剑。

服务器端和客户端同时对资源的优先级进行调整会让整个过程更加不透明并更加碎片化。然而最终结论由服务器做出,实际上是将这个权力转嫁给了开发者。

结论

我们调查发现“性能的大跃进”根本不存在,一些浏览器厂商早就知道了。

对网站性能的追求是一个权衡和差异化的过程。

类似我们所调查的这种包含大量图片的网页,选择多路 HTTP/2 连接还是多个 HTTP/1.x 连接,可以用延迟和图片平均下载时间的趋近作为临界点。对于高延迟与低带宽的恰当组合,小图片使用 HTTP/2 可以获得更好的结果。

HTTP/2 的实现还很年幼,围绕这一协议还需要做很多工作:

  • 资源权重优先级
  • 资源依赖性优先级
  • 多路模式的探索
  • 传输流和连接流控制

未来几年里,网上肯定会充斥着针对这些问题的调整、优化,以及必不可少的 Bug。重要的是我们必须了解这项新技术的动机并权衡,这样才能从炒作中获得价值。

有关图片优化的一个注解

对于 Discover 作品库这种页面,进一步的图片优化无疑会降低 HTTP/1 和 HTTP/2 用户完整视觉呈现的速度,而 HTTP/2 用户能否从中获得较大收益这一点目前还不明显。我们还需要考虑为整个平台实施图片优化解决方案所造成的工作量和开销。

作为一种设计作品商店,图片质量至关重要。我们对此非常在意,因为对图片进行不当的或过度的优化也会对用户体验产生消极影响。

我们会经常对整个堆栈的复杂度、处理大量预览图的成本,以及其他用户体验改进措施的机会成本进行评估。在研究适合的响应性解决方案过程中,目前 HTTP/2 这种先进的缓存和低开销交付方式正好提供了一种恰当的平衡。

致谢

本文得到了 Andrew Krespanis Ben Schwarz 的技术加工。谢谢你们。

作者 Michael Mifsud 阅读英文原文 Real–world HTTP/2: 400gb of images per day


感谢韩婷对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2016 年 8 月 10 日 17:182904
用户头像

发布了 283 篇内容, 共 84.6 次阅读, 收获喜欢 34 次。

关注

评论

发布
暂无评论
发现更多内容

架构师训练营 第十周作业

文江

TypeScript | 第六章:理解声明合并,以及编写声明文件

梁龙先森

typescript 前端 七日更

亚马逊 CTO 预测 2021 将改变世界的八大技术趋势:云加速向边缘推进

亚马逊AWS官方博客

云计算 AWS

【mybatis-plus】什么是乐观锁?如何实现“乐观锁”

Java架构师迁哥

bit位操作及其算法应用

Skysper

算法 位运算

大厂offer直通车:并发编程28题+JVM21题+Redis 16题+Java集合22题

Java架构之路

Java 程序员 架构 面试 编程语言

一个月吃透这份阿里高级专家的《Java500道面试手册》成功拿下了腾讯offer!

Java架构之路

Java 程序员 架构 面试 编程语言

职责链模式

soolaugust

设计模式 七日更 职责链模式

第十周作业

Jack

面试官:小伙子我们先来唠唠并发编程的几大核心知识点

程序员小毕

Java 架构 面试 并发编程 AQS

Spring源码高级笔记之——Spring AOP应用

Java架构师迁哥

Presto入门

HQ数字卡

presto 七日更

金融知识图谱的构建与应用

DataFunTalk

AI 知识图谱

四年Java开发,面试核心知识点(腾讯+阿里+快手面经)附答案

Java成神之路

Java 程序员 架构 面试 编程语言

星环科技作为信通院隐私计算联盟成员亮相2020数据资产管理大会

星环科技

大数据

第十周课后练习

晴空万里

极客大学架构师训练营

谷歌大佬回国发展,吊打各大厂面试官!吐血总结大厂面试高频点及笔记解析

Java成神之路

Java 程序员 架构 面试 编程语言

工作1-3年的Java工程师们,如何变得更值钱?,这2个点帮你8个月达到阿里P7水平

Java成神之路

Java 程序员 架构 面试 编程语言

2021年阿里、腾讯、百度、华为、京东、美团和滴滴最新Java面试题汇集!

Java架构之路

Java 程序员 架构 面试 编程语言

写技术文章给我带来什么好处?

小林coding

程序人生

注册中心Eureka源码解析

李浩宇/Alex

华为大佬亲自手码Dubbo服务暴露源码解析!这次够清楚了吧

比伯

Java 编程 架构 程序人生 计算机

久等了,Rancher 2.5中文文档新鲜出炉

RancherLabs

容器 k8s

微服务网关的技术架构

积极&丧

史上最全1000道Java高频面试题:集合、IO流、多线程、网络、算法、Git、设计模式、springboot

Java架构之路

Java 程序员 架构 面试 编程语言

北漂七年Java开发的一路辛酸史:面试腾讯、阿里、美团、字节后的一点心得

Java架构之路

Java 程序员 架构 面试 编程语言

思考-国际化系统表结构设计

BerryMew

Multi-Architecture镜像制作指南已到,请查收!

华为云开发者社区

Docker Kubernetes 容器 镜像 Multi-Architecture

瞬间起飞!腾讯大神纯手撸“架构师成手册”网友看完直呼NB!

比伯

Java 编程 架构 面试 计算机

分布式缓存架构设计和一致性HASH

我们新四军不拿群众一针一线

科技抗疫,少年可期,为这群有AI的天使开发者疯狂打call

华为云开发者社区

人工智能 华为云 modelarts 医疗AI 对象存储服务OBS

InfoQ 极客传媒开发者生态共创计划线上发布会

InfoQ 极客传媒开发者生态共创计划线上发布会

HTTP/2的应用实战:每天400gb图片-InfoQ