深入了解HTTP/2的前世今生以及Web性能优化总结

HTTP/2的出现,无疑对Web性能的提升带来了巨大的助力,改变了Web开发者优化网站的方式,但之前一直对它处于模糊的状态,只知道一些零零碎碎的知识,周末终于静下心来,从HTTP1开始,找到HTTP/2的存在及其存在必然性,整理了一些内容如下,希望能对有需要的同学产生一点点帮助。

分析之前,先来点直观好玩的吧

一、让人兴奋的HTTP/2

这个网站做了一个测试:分别利用HTTP/1和HTTP/2协议来下载一张大图(该大图由多张小图组成),HTTP/2完胜

点进去看看? [HTTP/2 is the future of the Web, and it is here!]

有个成语叫“事出有因”,每个事物都有其存在的意义(原因),而HTTP/2的诞生自然来自于HTTP/1的一些痛点

二、爷爷HTTP/1的痛点以及解决办法

HTTP(应用层)建立在TCP(传输层)之上,HTTP协议的一些瓶颈以及性能优化都是建立在TCP协议本身的特性之上。

所以谈HTTP之前还是得对TCP有一点点的了解(比如对三次握手、四次挥手、慢启动、往返时延RTT、拥塞窗口cwnd……)

起码得知道三次握手和四次挥手是为了防止了服务器端的一直等待而浪费资源;

知道慢启动是为了避免拥塞;

知道RTT和cwnd的概念是什么

传送门:[TCP慢启动、拥塞避免、快速重传、快速恢复 - CSDN博客]

影响网络请求的主要因素有两个:带宽和延迟

带宽跟网络基础建设相关暂不谈,所以延迟成了web工程师们的头号公敌。

http1.0被抱怨最多的两个问题

> 理解下面两个问题有一个十分重要的前提:客户端是依据域名来向服务器建立连接,一般PC端浏览器会针对单个域名的server同时建立6~8个连接,手机端的连接数则一般控制在4~6个。显然连接数并不是越多越好,资源开销和整体延迟都会随之增大。

1、连接无法复用

连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。

解决方案:

①HTTP持久连接:Connection:Keep-Alive [HTTP持久连接],痛点在于当前请求必须彻底完成后,下一请求才能正确发送。

②http long-polling:长轮询

③http streaming:建立起一个tcp连接后,服务器不会结束streaming请求,持续的通过这个通道返回最新的业务数据,数据通道也是单向的,除非客户端自动断开,否则一直保持连接

④websocket:也是基于tcp协议,提供双向的数据通道,优势在于提供了message的概念,同时又提供了传统的http所缺少的长连接功能

2、head of line blocking 线头阻塞

head of line blocking会导致带宽无法被充分利用,以及后续健康请求被阻塞,健康的请求会被不健康的请求影响,而且这种体验的损耗受网络环境影响,出现随机且难以监控

解决方案: [HTTP管线化]

基于HTTP/1的其他优化手段

1、Spriting(图片合并):但有时候只需要其中一张小图,就会浪费流量

2、Inlining(内容内嵌):比如把图片转化为base64编码后内嵌到总文件中,问题同上

3、Concatenation(文件合并):粒度变大,一个小的js代码改动会导致整个js文件被下载

4、Domain Sharding(域名分片):浏览器或者客户端是根据domain(域名)来建立连接,多建立几个sub domain(子域名),那么同时可以建立的http请求就会更多,连接数变多之后,受限制的请求就不需要等待前面的请求完成才能发出了;只有在请求数非常之多的场景下才有明显的效果,移动端建议不要使用 [Why Domain Sharding is Bad News for Mobile Performance and Users]

三、爸爸SPDY的改进

HTTP/1存在不少问题,2012年google提出了SPDY的方案,直击HTTP/1痛点

1、多路复用(multiplexing)

多路复用通过多个请求stream共享一个tcp连接的方式,解决了http1.x holb(head of line blocking)的问题,降低了延迟同时提高了带宽的利用率

2、请求优先级(request prioritization)

SPDY允许给每个request设置优先级,这样重要的请求就会优先得到响应

3、header压缩

SPDY对header的压缩率可以达到80%以上

4、server推送(server push)

开启server push之后,server通过X-Associated-Content header(X-开头的header都属于非标准的,自定义header)告知客户端会有新的内容推送过来。在用户第一次打开网站首页的时候,server将资源主动推送过来可以极大的提升用户体验。

5、server暗示(server hint)

和server push不同的是,server hint并不会主动推送内容,只是告诉有新的内容产生,内容的下载还是需要客户端主动发起请求。server hint通过X-Subresources header来通知

四、新生代HTTP/2及其特点

HTTP/1.x是一个文本协议,这注定它是非常冗余的协议,HTTP/2改变了这一点,在HTTP/1.x的语义上,将文本数据封装在帧里,并采用二进制编码

http2.0的格式定义更接近tcp层的方式,虽然看上去协议的格式和http1.x完全不同了,实际上http2.0并没有改变http1.x的语义,只是把原来http1.x的header和body部分用frame重新封装了一层而已。调试的时候浏览器甚至会把http2.0的frame自动还原成http1.x的格式

111

理解HTTP/2之前,要先理解两个概念 帧(frame)和流(stream)[HTTP/2中多路复用:帧(frame)和流(stream)]

HTTP/2和SPDY不同的地方在于,它是业界标准,而SPDY是chrome自家的孩子,马虎不得,一言一行都得考虑明星效应

所以它有几个设计前提

  • 客户端向server发送request这种基本模型不会变。
  • 老的scheme不会变,使用http://和https://的服务和应用不会要做任何更改,不会有http2://。
  • 使用http1.x的客户端和服务器可以无缝的通过代理方式转接到http2.0上。
  • 不识别http2.0的代理服务器可以将请求降级到http1.x。

基于以上原则,HTTP/2继承了SPDY的部分特性,并基于自己的明星定位做了一些扩展,下面介绍HTTP/2的基本概念及其如何优化Web性能的一些实践。

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

把HTTP/1.x每个请求都当作一个“流”,那么请求化成多个流,请求响应数据切成多个帧,不同流中的帧交错地发送给对方,这就是HTTP/2中的多路复用

112

2、多路复用(连接共享)

1、消除了多种通过捆绑相关资产以削减连接数量的长期解决思路的存在必要性

比如(上面的优化手段):

  • JS和CSS文件级联:将多个小型文件汇总成一个大型文件,从而降低总体请求数量
  • 雪碧图 * Domain Sharding(域名分片):增加整体TCP连接数量
  • 内容内嵌

2、请求优先级和请求依赖

一个request对应一个stream并分配一个id,这样一个连接上可以有多个stream,每个stream的frame可以随机的混杂在一起,接收方可以根据stream id将frame再归属到各自不同的request里面

所以,HTTP/2里的每个stream都可以设置优先级(Priority)和依赖(Dependency),真正解决了关键请求被阻塞的问题

3、header压缩

SPDY/2使用的是gzip压缩算法

HTTP/2采用的是一种叫HPACK的压缩算法

4、Server Push服务器推送

比如说客户端请求一个 html, html 里面含有 css 和图片,按照正常来讲,解析 html 之后要分别发出 CSS 的请求和图片的请求,但是如果服务端得知页面支持 server push,客户端便只需要发出 http 请求,而服务器直接将 css 和图片一起发出去,以致请求多个响应未发先至。这就是 server push 的作用,和 inlining 有点类似,但是相比 inlining 有两个好处,inlining 会影响缓存,会增大 html 的体积,包括后台模板的维护,这也便增加开发和维护成本,对于客户而言仅仅是多个请求。

5、重置连接

对于HTTP/1来说,是通过设置tcp segment里的reset flag来通知对端关闭连接的。这种方式会直接断开连接,下次再发请求就必须重新建立连接。

HTTP/2引入RST_STREAM类型的frame,可以在不断开连接的前提下取消某个request的stream,表现更好。

五、HTTP/2下的Web优化观念

1、核心理念

在HTTP/1下,大家的关注点都在减少向服务器发起的HTTP请求数,将尽可能多的资源塞进一个连接中,并寻找其他办法来避免浏览器出现线头阻塞。

在HTTP/2下,Web开发者应该专注于网站的缓存调优,而不是担心如何减少HTTP请求数。通用的法则是,传输轻量、细粒度的资源,以便独立缓存和并行传输。

这种转变的出现是因为HTTP/2的多路复用和头部压缩特性。 多路复用使得不同的请求共用一个TCP连接,允许多个资源并行下载,避免建立多个连接带来不必要的额外开销。它消除了HTTP/1.1中的线头阻塞问题。

头部压缩进一步减少了多个HTTP请求的开销,因为每个请求开销都小于未压缩的等价HTTP/1.1请求。

HTTP/2还有两个改变会影响到你的Web优化:流优先级和服务端推送。前者允许浏览器指定接受资源的顺序,后者允许服务端主动发送额外的资源。

2、将会被历史抛弃的HTTP/1优化手段

如此一来,上面HTTP/1的几种优化手段就应该被历史抛弃了:合并文件(webpack怎么办?思考题)、内联资源、雪碧图、细分域名

3、依然能复用的优化手段

①DNS预解析:减少DNS查询时间

DNS查询需要一个RTT时间,在浏览器级别,系统级别都会有层DNS缓存,之前解析过的可以直接从本机缓存获取,以减少延迟。 Web标准提供了一种DNS预解析技术,因为服务器是知道页面即将会发生哪些请求的,那我们可以在页面顶部,插入

<link rel="dns-prefetch" href="//host/">

让浏览器先解析一下这个域名。那么,后续扫到同域的请求,就可以直接从DNS缓存获取了。

此外,Web标准也提供prefetch,prerender的预加载技术。prefectch会在浏览器空闲的时候,向所提供的链接发起请求,而prerender不仅会请求,还会帮你在后台渲染页面。如果在一个页面中,你知道用户有很大概率去点某个链接,可以尝试把这个链接加到prefetch或prerender,那么用户就会秒开这个页面了。

②使用CDN 

将Web资源通过CDN放在地理上更靠近来访者的服务器节点上

③利用浏览器缓存

进一步利用内容分发网络,将资源存储在用户的本地浏览器缓存中,除了产生一个304 Not Modified响应之外,这避免了任何形式的数据在网络上传输

④最小化HTTP请求大小和响应大小

⑤避免不必要的重定向

重定向意味着要重新发起请求

这里要说的一种重定向是,访问HTTP站点,跳转到HTTPS,并不是指资源缓存的重定向获取 避免这种跳转,我们可以用HSTS策略告诉浏览器,以后访问我这个站点,必须用HTTPS协议来访问,让浏览器帮忙做转换,而不是请求到了服务器后,才知道要转换

在响应头部加上 Strict-Transport-Security: max-age=31536000即可

六、HTTP/2目前存在的问题以及使用限制

1、HTTP2.0最大的亮点在于多路复用,而多路复用的好处只有在http请求量大的场景下才明显,所以目前来说,可能更适用于浏览器浏览大型站点的时候。

2、HTTP2.0对于ssl的依赖比较强 虽然HTTP2.0也可以不走ssl,有些场景确实可能不适合https,比如对代理服务器的cache依赖,对于内容安全性不敏感的get请求可以通过代理服务器缓存来优化体验

3、移动端iOS9+自动支持HTTP/2,Android理论上来说需要5.0以上才支持(这个理论上非绝对,这里不说了)

七、后记

感谢您耐心看到这里,希望有所收获!

如果不是很忙的话,麻烦点个star⭐【Github博客传送门】,举手之劳,却是对作者莫大的鼓励。

我在学习过程中喜欢做记录,分享的是自己在前端之路上的一些积累和思考,希望能跟大家一起交流与进步,更多文章请看【amandakelake的Github博客】

 

参考

HTTP/2.0 相比1.0有哪些重大改进? - 知乎

从TCP、HTTP/1的问题上分析了为何会诞生HTTP/2 排名第二的那篇文章更加详细

[Web 开发者的 HTTP/2 性能优化指南]

与HTTP/1做了对比,容易理解和记忆

[Web 的现状:网页性能提升指南 - 前端郭高工 - SegmentFault 思否]

在HTTP/1的基础上,讲的比较详细有条理

【网络协议】Web协议未来优化指南

对TCP、HTTP1、HTTPS、SPDY、HTTP2等几种协议做了对比区分

作者:amandakelake
链接:https://juejin.im/post/5aaf51daf265da239376dfde
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。