在讨论页面加载性能问题时,我经常听到有人说“HTTP/2推送可以解决这问题”,但我对这个技术的了解不多,于是打算深入研究一下。
HTTP/2推送远比我最初想象中更复杂,也更底层,但最让我措手不及的地方在于,这种技术在不同浏览器上的表现竟然有这么大的差别,本来我还觉得这技术已经足够成熟,可以在生产环境中使用了。
本文并不是那种认为“HTTP/2推送一无是处”的吐槽文。我觉得HTTP/2推送真的很强大,以后还会更加完善,但并不算能解决所有问题的万灵药。
完整的Fetch路径
在页面和目标服务器间,横亘着一系列可能拦截请求的缓存和其他机制:
当人们希望尝试或向别人解释Git或其他看得见的东西时,通常会使用类似上面这样的流程示意图,在本来就懂的人看来,这样的示意图一目了然,但不懂的人往往会一头雾水。如果你也有这种感觉,那要先说声抱歉了!希望下文能帮你更好地理解。
HTTP/2推送的工作原理页面:嘿example.com,能把你的首页让我看一看吗?
服务器:没问题!哦,在我给你发送首页的同时,还需要发送一些样式表、图片、JavaScript,以及一些JSON。
页面:额,好的。
页面:我已经看到HTML了,但貌似还需要一个样式……哦,好像你已经发过来了,酷!
相关厂商内容
超级App的实时性能监控与性能优化实践 微信图片视频背后的EB级存储引擎设计 漏斗模型:京东物流系统高并发架构演进之路 如何开发一个商业智能推荐系统? 2017年,你应该关注这些运维技术热点
相关赞助商
ArchSummit深圳2017,7月7-8日,深圳·华侨城洲际酒店,精彩内容抢先看
服务器响应请求时,可以顺便包含额外的资源。例如包含一系列请求报头,这样稍后浏览器就知道如何匹配不同报头。这些额外的资源位于缓存中,当浏览器请求的资源与缓存中的匹配时即可直接从缓存中获取。
这种方法可以改善性能,原因在于可以提前发送可能需要的资源,而不需要等待浏览器索取,因此可以提高页面加载速度。
多年来我对HTTP/2推送的了解仅限于此,听起来挺简单,但魔鬼往往隐藏在细节中……
任何东西都可以使用推送缓存HTTP/2推送是一种底层网络功能,用到网络栈的任何东西都可以使用该功能。但只有确保一致性以及可预测性,才能发挥最大作用。
我试着推送一些资源,并通过下列方式收集:
fetch()
XMLHttpRequest
<link href="https://www.linuxidc.com/…">
<script src="https://www.linuxidc.com/…">
<iframe src="https://www.linuxidc.com/…">
为了解浏览器能否对正在推送中的内容进行匹配,我还降低了所推送资源主体的交付速度。这一过程中用到零零散散的测试套件已发布至GitHub。
Chrome - 良好支持
Safari - 糟糕支持
Firefox - 良好支持
Edge - 部分支持
Edge使用fetch()、XMLHttpRequest或<iframe>无法从推送缓存中获取所需项(问题描述,含视频)。
Safari最奇怪。到底用或不用推送缓存,似乎是通过抛硬币决定的。Safari遵从于OSX的闭源网络栈,但我觉得一些Bug是Safari自身造成的。似乎是因为打开了太多连接,导致被推送的项分散在不同连接中。这意味着只有足够好运,请求与推送使用了同一个连接,此时才能命中缓存,不过这就超过我的了解范围了(问题描述,含视频)。
所有浏览器(Safari行事怪异时除外)都可以使用匹配的推送项,哪怕推送工作还在进行中。这一点倒是不错。
然而不幸的是,只有Chrome为此提供了开发工具方面的支持。开发工具的网络窗格可以告诉你哪些项是从推送缓存中获取的。
建议如果浏览器无法从推送缓存中获取项,那么最终的速度甚至会比完全不进行推送更慢。