HTTP/2的出现,无疑对Web性能的提高带来了巨大的助力,改变了Web开发者优化网站的方式,但以前一直对它处于模糊的状态,只知道一些零零碎碎的知识,周末终于静下心来,从HTTP1开始,找到HTTP/2的存在及其存在必然性,整理了一些内容以下,但愿能对有须要的同窗产生一点点帮助。css
分析以前,先来点直观好玩的吧html
这个网站作了一个测试:分别利用HTTP/1和HTTP/2协议来下载一张大图(该大图由多张小图组成),HTTP/2完胜 前端
点进去看看? [HTTP/2 is the future of the Web, and it is here!] webpack
有个成语叫“事出有因”,每一个事物都有其存在的意义(缘由),而HTTP/2的诞生天然来自于HTTP/1的一些痛点
git
HTTP(应用层)创建在TCP(传输层)之上,HTTP协议的一些瓶颈以及性能优化都是创建在TCP协议自己的特性之上。 github
因此谈HTTP以前仍是得对TCP有一点点的了解(好比对三次握手、四次挥手、慢启动、往返时延RTT、拥塞窗口cwnd……) web
起码得知道三次握手和四次挥手是为了防止了服务器端的一直等待而浪费资源;算法
知道慢启动是为了不拥塞;chrome
知道RTT和cwnd的概念是什么 segmentfault
传送门:[TCP慢启动、拥塞避免、快速重传、快速恢复 - CSDN博客]
影响网络请求的主要因素有两个:带宽和延迟
带宽跟网络基础建设相关暂不谈,因此延迟成了web工程师们的头号公敌。
http1.0被抱怨最多的两个问题
> 理解下面两个问题有一个十分重要的前提:客户端是依据域名来向服务器创建链接,通常PC端浏览器会针对单个域名的server同时创建6~8个链接,手机端的链接数则通常控制在4~6个。显然链接数并非越多越好,资源开销和总体延迟都会随之增大。
链接没法复用会致使每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。
解决方案:
①HTTP持久链接:Connection:Keep-Alive [HTTP持久链接],痛点在于当前请求必须完全完成后,下一请求才能正确发送。
②http long-polling:长轮询
③http streaming:创建起一个tcp链接后,服务器不会结束streaming请求,持续的经过这个通道返回最新的业务数据,数据通道也是单向的,除非客户端自动断开,不然一直保持链接
④websocket:也是基于tcp协议,提供双向的数据通道,优点在于提供了message的概念,同时又提供了传统的http所缺乏的长链接功能
head of line blocking会致使带宽没法被充分利用,以及后续健康请求被阻塞,健康的请求会被不健康的请求影响,并且这种体验的损耗受网络环境影响,出现随机且难以监控
解决方案: [HTTP管线化]
一、Spriting(图片合并):但有时候只须要其中一张小图,就会浪费流量
二、Inlining(内容内嵌):好比把图片转化为base64编码后内嵌到总文件中,问题同上
三、Concatenation(文件合并):粒度变大,一个小的js代码改动会致使整个js文件被下载
四、Domain Sharding(域名分片):浏览器或者客户端是根据domain(域名)来创建链接,多创建几个sub domain(子域名),那么同时能够创建的http请求就会更多,链接数变多以后,受限制的请求就不须要等待前面的请求完成才能发出了;只有在请求数很是之多的场景下才有明显的效果,移动端建议不要使用 [Why Domain Sharding is Bad News for Mobile Performance and Users]
HTTP/1存在很多问题,2012年google提出了SPDY的方案,直击HTTP/1痛点
多路复用经过多个请求stream共享一个tcp链接的方式,解决了http1.x holb(head of line blocking)的问题,下降了延迟同时提升了带宽的利用率
SPDY容许给每一个request设置优先级,这样重要的请求就会优先获得响应
SPDY对header的压缩率能够达到80%以上
开启server push以后,server经过X-Associated-Content header(X-开头的header都属于非标准的,自定义header)告知客户端会有新的内容推送过来。在用户第一次打开网站首页的时候,server将资源主动推送过来能够极大的提高用户体验。
和server push不一样的是,server hint并不会主动推送内容,只是告诉有新的内容产生,内容的下载仍是须要客户端主动发起请求。server hint经过X-Subresources header来通知
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的格式
理解HTTP/2以前,要先理解两个概念 帧(frame)和流(stream)[HTTP/2中多路复用:帧(frame)和流(stream)]
HTTP/2和SPDY不一样的地方在于,它是业界标准,而SPDY是chrome自家的孩子,马虎不得,一言一行都得考虑明星效应
因此它有几个设计前提
基于以上原则,HTTP/2继承了SPDY的部分特性,并基于本身的明星定位作了一些扩展,下面介绍HTTP/2的基本概念及其如何优化Web性能的一些实践。
把HTTP/1.x每一个请求都看成一个“流”,那么请求化成多个流,请求响应数据切成多个帧,不一样流中的帧交错地发送给对方,这就是HTTP/2中的多路复用
一、消除了多种经过捆绑相关资产以削减链接数量的长期解决思路的存在必要性
好比(上面的优化手段):
二、请求优先级和请求依赖
一个request对应一个stream并分配一个id,这样一个链接上能够有多个stream,每一个stream的frame能够随机的混杂在一块儿,接收方能够根据stream id将frame再归属到各自不一样的request里面
因此,HTTP/2里的每一个stream均可以设置优先级(Priority)和依赖(Dependency),真正解决了关键请求被阻塞的问题
SPDY/2使用的是gzip压缩算法
HTTP/2采用的是一种叫HPACK的压缩算法
好比说客户端请求一个 html, html 里面含有 css 和图片,按照正常来说,解析 html 以后要分别发出 CSS 的请求和图片的请求,可是若是服务端得知页面支持 server push,客户端便只须要发出 http 请求,而服务器直接将 css 和图片一块儿发出去,以至请求多个响应未发先至。这就是 server push 的做用,和 inlining 有点相似,可是相比 inlining 有两个好处,inlining 会影响缓存,会增大 html 的体积,包括后台模板的维护,这也便增长开发和维护成本,对于客户而言仅仅是多个请求。
对于HTTP/1来讲,是经过设置tcp segment里的reset flag来通知对端关闭链接的。这种方式会直接断开链接,下次再发请求就必须从新创建链接。
HTTP/2引入RST_STREAM类型的frame,能够在不断开链接的前提下取消某个request的stream,表现更好。
在HTTP/1下,你们的关注点都在减小向服务器发起的HTTP请求数,将尽量多的资源塞进一个链接中,并寻找其余办法来避免浏览器出现线头阻塞。
在HTTP/2下,Web开发者应该专一于网站的缓存调优,而不是担忧如何减小HTTP请求数。通用的法则是,传输轻量、细粒度的资源,以便独立缓存和并行传输。
这种转变的出现是由于HTTP/2的多路复用和头部压缩特性。 多路复用使得不一样的请求共用一个TCP链接,容许多个资源并行下载,避免创建多个链接带来没必要要的额外开销。它消除了HTTP/1.1中的线头阻塞问题。
头部压缩进一步减小了多个HTTP请求的开销,由于每一个请求开销都小于未压缩的等价HTTP/1.1请求。
HTTP/2还有两个改变会影响到你的Web优化:流优先级和服务端推送。前者容许浏览器指定接受资源的顺序,后者容许服务端主动发送额外的资源。
如此一来,上面HTTP/1的几种优化手段就应该被历史抛弃了:合并文件(webpack怎么办?思考题)、内联资源、雪碧图、细分域名
①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请求大小和响应大小
⑤避免没必要要的重定向
重定向意味着要从新发起请求
在响应头部加上 Strict-Transport-Security: max-age=31536000
便可
一、HTTP2.0最大的亮点在于多路复用,而多路复用的好处只有在http请求量大的场景下才明显,因此目前来讲,可能更适用于浏览器浏览大型站点的时候。
二、HTTP2.0对于ssl的依赖比较强 虽然HTTP2.0也能够不走ssl,有些场景确实可能不适合https,好比对代理服务器的cache依赖,对于内容安全性不敏感的get请求能够经过代理服务器缓存来优化体验
三、移动端iOS9+自动支持HTTP/2,Android理论上来讲须要5.0以上才支持(这个理论上非绝对,这里不说了)
感谢您耐心看到这里,但愿有所收获!
若是不是很忙的话,麻烦点个star⭐【Github博客传送门】,举手之劳,倒是对做者莫大的鼓励。
我在学习过程当中喜欢作记录,分享的是本身在前端之路上的一些积累和思考,但愿能跟你们一块儿交流与进步,更多文章请看【amandakelake的Github博客】
参考
从TCP、HTTP/1的问题上分析了为什么会诞生HTTP/2 排名第二的那篇文章更加详细
与HTTP/1作了对比,容易理解和记忆
[Web 的现状:网页性能提高指南 - 前端郭高工 - SegmentFault 思否]
在HTTP/1的基础上,讲的比较详细有条理
对TCP、HTTP一、HTTPS、SPDY、HTTP2等几种协议作了对比区分