资讯专栏INFORMATION COLUMN

【译】HTTP/2 Server Push 实践:单 Link 报头包含多资源场景

bbbbbb / 3407人阅读

摘要:记录以下资源备忘也就是本文译文标题为意译,原标题为,恐有不当,特此说明。译者注翻译本文时译者使用的确实无法看到信息,建议使用最新金丝雀版本一探究竟。应用程序不应当依赖于服务器推送的可用性及其使用。

本文转载自:众成翻译
译者:文蔺
链接:http://www.zcfy.cc/article/883
原文:https://blog.cloudflare.com/http-2-server-push-with-multiple-assets-per-link-header/

译者注

译者在做自己的一个小工具(抓取博客的 Chrome 扩展)的时候,使用 jQuery 辅助作为 DOM 解析器,为了避免加载图片、脚本、样式表等无用的资源,在将字符串传给 $ 的时候,先对字符串中的相关标签进行了处理。

但遇到某个网站的时候,一直疑惑不解,明明已经做了替换,但通过 Chrome Devtools 能看到,部分资源还是会下载。几经折腾,发现还是因为自己懂得太少了。

查看请求该页面时的 header,可以看到了如下信息:

link:; rel=preload; as=style, ; rel=preload; as=image, ; rel=preload; as=image, ; rel=preload; as=image, ; rel=preload; as=image, ; rel=preload; as=image, ; rel=preload; as=image, ; rel=preload; as=image, ; rel=preload; as=image, ; rel=preload; as=image

于是,大概能猜出来上述问题的原因。这有点类似如一些站点会使用的 标签(顺带一句,截至 2016 年 7 月 17 日,caniuse 数据:China = 26.83%;Global = 44.59%)。

于是深入挖掘了一下。来看看 W3C 标准是怎么说的(同样由译者翻译):

例如,应用可以使用 preload 关键词,提前、高优先级、不阻塞渲染地拉取的 CSS 资源,它会在适当的时候被使用:

例一:使用标签




例二:使用 HTTP Header

Link: ; rel=preload; as=style

上面的例子说明,资源可以通过声明性标记、HTTP header link 来指定,或者使用 JavaScript 预定。

记录以下资源备忘:

https://w3c.github.io/preload/

http://caniuse.com/#search=preload

http://stackoverflow.com/questions/36641137/how-exactly-does-link-rel-preload-work

https://blog.cloudflare.com/http-2-server-push-with-multiple-assets-per-link-header/(也就是本文)

译文标题为意译,原标题为 HTTP/2 Server Push with multiple assets per Link header,恐有不当,特此说明。

另,为加强理解 link 报头与 HTTP/2 Server Push 二者,译文正文后附有 W3C preload 标准中 “Server Push (HTTP/2)” 一节译文。或有助于读懂本文。

注: 译文中凡是 “link 响应头” 的名词,英文为 “Link header”,翻译为“响应头 Link 字段”或许更恰当。

正文

四月份的时候,我们宣布为所有的 CloudFlare 网站添加了 HTTP/2 Server Push 试验性支持。这样做是为了让客户能够在该新功能的基础上进行迭代。


CC BY 2.0 image by https://www.flickr.com/photos/mryipyop/

我们的 Server Push 实现,利用了 HTTP Link 报头,这在 W3C Preload 工作草案中有详细描述。

同样,我们还展示了,如何在 PHP 代码 中实现 Server Push,许多人已经开始测试、使用该特性了。

然而,我们的初始版本有很严格的限制:使用 Server Push,则每个 link 报头中,最多只能指定一个资源,另外,很多 CMS 和 Web 开发平台都不允许存在多个 link 报头。

现在该问题已得到解决,多个资源可以通过单个 link 报头推送。修改是实时生效的,如果你的浏览器支持 HTTP/2 的话,你正在阅读的本文就使用了该方式推送资源。

当 CloudFlare 读到源服务器(origin web server)的 link 报头时,它从中移除其中已通过 Server Push 推送给浏览器的资源。这样一来,要 debug link 和 Server Push 问题就困难了,所以我们又加上了一个叫做 Cf-H2-Pushed 的报头,它包含已经推送过的资源。

举个例子。打开最近的这篇博客,源服务器就会发送以下报头:

Cache-Control: public, max-age=0
Content-Encoding: gzip
Content-Length: 33640
Content-Type: text/html; charset=utf-8
Date: Wed, 29 Jun 2016 16:09:37 GMT
Expires: Wed, 29 Jun 2016 16:10:07 GMT
Link: ; rel=preload; as=style,; rel=preload; as=script,; rel=preload; as=image,; rel=preload; as=image,; rel=preload; as=script,; rel=preload; as=script,; rel=preload; as=script
Vary: Accept-Encoding
X-Ghost-Cache-Status:From Cache
X-Powered-By: Express

CloudFlare 决定使用使用 HTTP/2 Server Push 推送这些资源:

 `/assets/css/screen.css?v=5fc240c512`,
 `/content/images/2016/06/Timeouts-001.png`,
 `/content/images/2016/06/Timeouts-002.png`,
 `/assets/js/jquery.fitvids.js?v=5fc240c512`

响应通过 CloudFlare 的时候,这些资源将从 link 报头终移除,通过 Server Push 推送,并被添加到 Cf-H2-Pushed 报头中:

cache-control:public, max-age=30
cf-cache-status:EXPIRED
cf-h2-pushed:,,,
content-encoding:gzip
content-type:text/html; charset=utf-8
date:Wed, 29 Jun 2016 16:09:37 GMT
expires:Wed, 29 Jun 2016 16:10:07 GMT
link:; rel=preload; as=script,; rel=preload; as=script,; rel=preload; as=script
server:cloudflare-nginx
status:200 OK
vary:Accept-Encoding
x-ghost-cache-status:From Cache
x-powered-by:Express 

在 Google Chrome 金丝雀版本(Google Chrome Canary)的开发者视图中可以看得很清楚。(译者注:翻译本文时译者使用的 Chrome 51.0.2704.106 m (64-bit) 确实无法看到 Push 信息,建议使用最新金丝雀版本一探究竟。)

结尾

如果你在使用 Server Push,请和我们联系。推送不同类型的资源(图片 vs 样式表 vs 脚本)、解决最佳的推送数量(目前我们支持 每页最多 50 条资源),我们对相关经验十分感兴趣。

附: Server Push (HTTP/2)

原文地址: https://w3c.github.io/preload/#server-push-http-2

HTTP/2 ([RFC7540]) 允许服务器先发制人地向客户端发送(“推送”)响应。推送的响应(pushed response)在语义上(semantically)与服务器对请求的响应(server responding to a request)是等价的,而且类似于预加载的响应(preloaded response);它会被浏览器保存,在匹配到应用启动的其他请求的时候被执行。像这样的,从应用角度来看,使用预加载和服务器推送的请求,并无差别。

服务器可能会为应用定义的那些有权限的 preload link 资源启用服务器推送。对那些声明的 preload link 资源来说,启用服务器推送消除了客户端和服务器之间的请求往返。可选地,如果某个通过 link 报头(RFC5988)声明的资源不希望使用服务器推送,开发者*可以使用 nopush 目标属性(RFC5988] section 5.4) 向服务器提供一个选择性退出的信号。示例如下:

例三

Link: ; rel=preload; as=style; nopush
Link: ; rel=preload; as=script

Note
上面的示例,向一个可以使用 HTTP/2 推送的服务器提示, /app/style.css 不应被推送(例如,来源方可能有额外信息显示其已经存在于缓存中),而 /app/script.js 应当可以作为服务器推送的候选资源。

为 preload link 启用服务器推送是一个可选的优化项。比方说,服务器可能不会启用推送,如果它认为响应在客户端缓存中可以拿到:客户端会处理预加载指令,检查相关缓存,如果找不到资源则会发送请求。另外,服务器可能因为运维问题而不会启用推送,比如说可用服务器资源或者其他考量。最后,服务器推送的启用取决于协议的 HTTP/2 连接设置:客户端可能会限制或完全禁用服务器推送的使用。应用程序不应当依赖于服务器推送的可用性及其使用。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/87782.html

相关文章

  • HTTP/2 技术调研和性能分析

    摘要:消息与逻辑请求或响应消息对应的完整的一系列帧。声明数据流依赖关系指出,应尽可能先向父数据流分配资源,然后再向其依赖项分配资源。数据流应先于和获得完整资源分配和应先于和获得相同的资源分配和应基于其权重获得比例分配。 转载自 | 小米运维(公众号 ID:MI-SRE)showImg(https://segmentfault.com/img/bVbbesG?w=344&h=344); HTT...

    hlcfan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<