HTTP/2 与 WEB 性能优化(一)

今年二月份,Google 宣布将在 16 年初放弃对 SPDY 的支持,随后 Google 自家支持 SPDY 协议的服务都切到了 HTTP/2。今年 5 月 14 日,HTTP/2 以 RFC 7540 正式发布。目前,浏览器方面,Chrome 40+ 和 Firefox 36+ 都正式支持了 HTTP/2;服务器方面,著名的 Nginx 表示会在今年底正式支持 HTTP/2。

不得不说这几年 WEB 技术一直在突飞猛进,爆炸式发展。昨天还觉得 HTTP/2 很遥远,今天已经遍地都是了。对于新鲜事物,有些人不愿意接受,觉得好端端为什么又要折腾;有些人会盲目崇拜,认为它是能拯救一切的救世主。HTTP/2 究竟会给前端带来什么,什么都不是?还是像某些人说的「让前端那些优化小伎俩直接退休」?我打算通过写一系列文章来尝试回答这个问题,今天是第一篇。

提出问题

我们知道,一个页面通常由一个 HTML 文档和多个资源组成。有一些很重要的资源,例如头部的 CSS、关键的 JS,如果迟迟没有加载完,会阻塞页面渲染或导致用户无法交互,体验很差。如何让重要的资源更快加载完是我本文要讨论的问题。

HTTP/1

分析

我们先来考虑资源外链的情况。通常,外链资源都会部署在 CDN 上,这样用户就可以从离自己最近的节点上获取数据。一般文本文件都会采用 gzip 压缩,实际传输大小是文件大小的几分之一。服务端托管静态资源的效率通常非常高,服务端处理时间几乎可以忽略。在忽略网络因素、传输大小以及服务端处理时间之后,用户何时能加载完外链资源,很大程度上取决于请求何时能发出去,这主要受下面三个因素影响:

浏览器阻塞(Stalled):浏览器会因为一些原因阻塞请求。例如在 rfc2616 中规定浏览器对于一个域名,同时只能有 2 个连接(HTTP/1.1 的修订版中去掉了这个限制,详见 rfc7230,因为后来浏览器实际上都放宽了限制),超过浏览器最大连接数限制,后续请求就会被阻塞。再例如现代浏览器在加载同一域名多个 HTTPS 资源时,会有意等第一个 TLS 连接建立完成再请求其他资源;

DNS 查询(DNS Lookup):浏览器需要知道目标服务器的 IP 才能建立连接。将域名解析为 IP 的这个系统就是 DNS。DNS 查询结果通常会被缓存一段时间,但第一次访问或者缓存失效时,还是可能耗费几十到几百毫秒;

建立连接(Initial connection):HTTP 是基于 TCP 协议的,浏览器最快也要在第三次握手时才能捎带 HTTP 请求报文。这个过程通常也要耗费几百毫秒;

当然我们一般都会给静态资源设置一个很长时间的缓存头。只要用户不清除浏览器缓存也不刷新,第二次访问我们网页时,静态资源会直接从本地缓存获取,并不产生网络请求;如果用户只是普通刷新而不是强刷,浏览器会在请求头带上协商字段 If-Modified-Since 或 If-None-Match,服务端对没有变化的资源会响应 304 状态码,告知浏览器从本地缓存获取资源。304 请求没有正文,非常小。

也就是说资源外链的特点是,第一次慢,第二次快。

再来看看资源内联的情况。把 CSS、JS 文件内容直接内联在 HTML 中的方案,毫无疑问会在用户第一次访问时有速度优势。但通常我们很少缓存 HTML 页面,这种方案会导致内联的资源没办法利用浏览器缓存,后续每次访问都是一种浪费。

解决

很早之前,就有网站开始针对第一次访问的用户将资源内联,并在页面加载完之后异步加载这些资源的外链版本,同时记录一个 Cookie 标记表示用户来过。用户再次访问这个页面时,服务端就可以输出只有外链版本的页面,减小体积。

这个方案除了有点浪费流量之外(一份资源,内联外链加载了两次),基本上能达到更快加载重要资源的效果。但是在流量更加宝贵的移动端,我们需要继续改进这个方案。

考虑到移动端浏览器都支持 localStorage,可以将第一次内联引入的资源缓存起来后续使用。缓存更新机制可以通过在 Cookie 中存放版本号来实现。这样,服务端收到请求后,首先要检查 Cookie 头中的版本标记:

如果标记不存在或者版本不匹配,就将资源内联输出,并提供当前版本标记。页面执行时,会把内联资源存入 localStorage,并将资源版本标记存入 Cookie;

如果标记匹配,就输出 JavaScript 片段,用来从 localStorage 读取并使用资源;

由于 Cookie 内容需要尽可能的少,所以一般只存总的版本号。这会导致页面任何一处资源变动,都会改变总版本号,进而忽略客户端所有 localStorage 缓存。要解决这个问题可以继续改进我们的方案:Cookie 中只存放用户唯一标识,用户和资源对应关系存在服务端。服务端收到请求后根据用户标识,计算出哪些资源需要更新,从而输出更有针对性的 HTML 文档。

这套方案要投入实际使用,要处理一系列异常情况,例如 JS / Cookie / localStorage 被禁用;localStorage 被写满;localStorage 内容损坏或丢失等等。考虑成本和实际收益,推荐只在移动项目中使用这种方案。

HTTP/2

对于 HTTP/2 来说,要解决前面这个问题简直就太容易了,开启「Server Push」即可。HTTP/2 的多路复用特性,使得可以在一个连接上同时打开多个流,双向传输数据。Server Push,意味着服务端可以在发送页面 HTML 时主动推送其它资源,而不用等到浏览器解析到相应位置,发起请求再响应。另外,服务端主动推送的资源不是被内联在页面里,它们有自己独立的 URL,可以被浏览器缓存,当然也可以给其他页面使用。

服务端可以主动推送,客户端也有权利选择接收与否。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送 RST_STREAM 帧来拒收。

可以看到,HTTP/2 的 Server Push 能够很好地解决「如何让重要资源尽快加载」这个问题,一旦普及开来,可以取代前面介绍过的 HTTP/1 时代优化方案。

作者:何妍 

来源:51CTO

时间: 2024-09-30 09:53:06

HTTP/2 与 WEB 性能优化(一)的相关文章

HTTP/2 与 WEB 性能优化(三)

在连续写了两篇关于「HTTP/2 与 WEB 性能优化」的文章后,今天来写这个系列的最后一篇.在正式开始之前,我们先来简单回顾下之前两篇文章: 「HTTP/2 与 WEB 性能优化(一)」的结论是:HTTP/2 的 Server Push 机制,可以让重要的 JS.CSS 等资源尽快加载,从而不再需要 HTTP/1 中「将重要资源内联在页面头部」的优化方案了. 「HTTP/2 与 WEB 性能优化(二)」的结论是:HTTP/2 支持了多路复用,HTTP 连接变得十分廉价,之前为了节省连接数所采用

java web性能优化问题

问题描述 java web性能优化问题 Java web后台性能优化: 1.可以把数据放在application里面: 2.可以把数据作为static变量的值,放在常量类里: 3.可以把数据放到缓存. 三种方式孰优孰劣,以及各自有什么优缺点? 解决方案 Java Web性能优化Java Web性能优化Java Web性能优化原则

Web性能优化:What? Why? How?

为什么要提升web性能? Web性能黄金准则:只有10%~20%的最终用户响应时间花在了下载html文档上,其余的80%~90%时间花在了下载页面组件上. web性能对于用户体验有及其重要的影响,根据著名的`2-5-8`原则: 当用户在2秒以内得到响应,会感觉系统的响应非常快 当用户在2-5秒之内得到响应,会感觉系统的响应速度还可以 当用户在5-8秒之内得到响应,会感觉系统的响应非常慢,但还可以接受 当用户在8秒之后都没有得到响应,会感觉系统糟透了,甚至系统已经挂掉:要么打开竞争对手的网站,要么

Apache的压力测试以及web性能优化的常用知识总结_Linux

什么是带宽? 误解:"数据在线路中的移动速度"."数据的传输速度" 我们所说的带宽是指数据的发送速度,比如百兆网卡,指网卡的最大发送速度是100Mbps,也就是说网卡在一秒钟最多可以发送100Mb的数据:相关的因素: 数据发送装置将二进制信号传送到线路的能力,也称信号传输频率,以及另一端数据接收装置对二进制信号接收的能力,也包括线路对传输频率的支持程度: 数据传输介质的并行度,等价于计算机系统总线宽度的概念:   习惯与约定 b:比特单位 bit: B:字节单位 B

Web性能优化系列 10个提升JavaScript性能的技巧_javascript技巧

Nicholas Zakas是一位 JS 大师,Yahoo! 首页的前端主程.他是<高性能 Javascript>的作者,这本书值得每个程序员去阅读. 当谈到 JS 性能的时候,Zakas差不多就是你要找的,2010年六月他在Google Tech Talk发表了名为<Speed Up Your Javascript>的演讲. 但 Javascript 性能优化绝不是一种书面的技术,Nicholas 的技术演进列出了10条建议,帮助你写出高效的 JS 代码. 1. 定义局部变量 当

web性能优化之:no-cache与must-revalidate深入探究

引言 稍微了解HTTP协议的前端同学,相比对Cache-Control不会感到陌生,性能优化时经常都会跟它打交道. 常见的值有有private.public.no-store.no-cache.must-revalidate.max-age等. 各个取值所代表的含义,网上总结挺多的,这里就不打算再进行逐一介绍,感兴趣的可以一起探讨交流. 本文仅挑no-cache.must-revalidate 这两个进行值进行探究对比.在项目实践中,这两个值用的比较多,也比较容易搞混. Cache-Contro

mysql数据库优化与mysql在web性能优化

数据库语句:     Ddl(数据定义语言)    alter  create   drop         Dml(数据操作语言)   inset  delete  update       Dtl(数据事务语言)  conmmit  rollback   savepoint       Select       Dcl(数据控制语句) grant赋权限  revoke回收        Mysql数据库优化: 1.  数据库表 要设计合理(符合3NF,有时候也需要适当的逆范式) 2.  Sq

web性能优化之javascript性能调优_javascript技巧

JavaScript 是一个比较完善的前端开发语言,在现今的 web 开发中应用非常广泛,尤其是对 Web 2.0 的应用.随着 Web 2.0 越来越流行的今天,我们会发现:在我们的 web 应用项目中,会有大量的 JavaScript 代码,并且以后会越来越多.JavaScript 作为一个解释执行的语言,以及它的单线程机制,决定了性能问题是 JavaScript 的软肋,也是 web 软件工程师们在写 JavaScript 需要高度重视的一个问题,尤其是针对 Web 2.0 的应用.绝大多

Web网站性能优化的相关技术

中介交易 SEO诊断 淘宝客 云主机 技术大厅 Web站点性能问题吸引或者迫使越来越多的人投入到这个问题的研究中来,产生了很多解决方案.下面是我根据自身的理解对这些技术进行了归类总结,如有不足之处欢迎拍砖. 一.提高服务器并发处理能力 我们总是希望一台服务器在单位时间内能处理的请求越多越好,这也成了web服务器的能力高低的关键所在.服务器之所以可以同时处理多个请求,在于操作系统通过多执行流体系设计,使得多个任务可以轮流使用系统资源,这些资源包括CPU.内存以及I/O等.这就需要选择一个合适的并发