最近读完《HTTP2 基础教程》,至关因而对 HTTP2 有了个大体的了解,本文已加入个人博客,感谢你们支持!css
互联网刚开始的时候,人们浏览网页只是为了阅读文字,随着时代的不断发展,人们对于网站的需求愈来愈高,一个网站不只仅要展现文字,还要展现图片,视频,3D 特效等。html
一、Web 页面引用的内容每一年都在增加,图片,JS,CSS 愈来愈大,也愈来愈多。git
二、Web 所依赖的资源也变得愈来愈复杂。github
三、大多数 Web 页面会关联数十个域名的资源,每个资源都须要经历一次 DNS,TCP,TLS 等。算法
人们对网站的需求愈来愈多,可是 HTTP 协议却发展很慢,HTTP1.1 已经存在 20 年了,却仍是当前社会中使用最普遍的协议。如下几个缺点也愈来愈被你们所关注:浏览器
一、队头阻塞,在请求响应中若是出现任何问题,剩下的工做都会被阻塞在那次请求应答以后。缓存
二、低效的 TCP 利用安全
拥塞窗口:在接收方确认数据包以前,发送方能够发出的 TCP 包的数量。(例如:若是拥塞窗口为 1,那么发送方发出 1 个数据包以后,只有接收方确认了那个包,才能发送下一个)。服务器
TCP 中有个概念叫慢启动,目的是为了让新链接搞清楚当前的网络情况,避免给已经拥堵的网络继续添乱。(它容许客户端在收到每一个确认回复后额外发送 1 个未确认包,这意味着新链接在收到 1 个确认回复后,能够发送 2 个数据包,在收到 2 个确认回复后,能够发 4 个,以此类推,直到达到上限值)cookie
三、臃肿的消息首部
虽然 HTTP1 提供了压缩请求内容
的机制,可是消息首部却没法压缩,若是算上 cookie,可能每次都会多发送几千个字节。
四、受限制的优先级设置
HTTP1 没有优先级一说,要么发起请求,要么不发起。
为了解决 HTTP1 的各类问题,你们也总结一下优化方案,咱们来依次介绍一下吧。
若是想在 HTTP 协议层面作优化,能够考虑下几点:
<link rel="dns-prefetch" href="//www.xxx.com" />
<link rel="preconnect" href="//www.xxx.com" />
咱们经常使用缓存来避免没必要要的请求,但要使用缓存必须遵照着两个概念:多用户之间可共享
,可以接受必定程度的旧数据
。
使用 Expires 首部,将资源失效的日期
告诉客户端,在失效如期以前,客户端都会直接使用缓存中的资源而不会发起请求
。
使用 Cache-Control 首部,进行更多的定制化缓存:
在请求中包含 HTTP 首部 Last Modified,仅当最新内容在首部中制定的日志以后被更新过,服务器才返回完整内容,不然返回 304.
在请求实体中包含实体校验码 ETag,它惟一标识所请求的资源,服务器会比较当前 ETag 与请求首部中收到 ETag,若是一致,就返回 304.
删除 html 文档中的注释,换行,空格等,减小资源大小。
因为 JS 在处理时,会阻止其余任何资源的下载和渲染,可能会带来没必要要的延迟。
一张图片中每每并非只有图片内容,每每还包含有一些图片元信息:地理位置信息,时间戳,尺寸,像素等。而这些信息对于页面并无声明用,还会增长图片的大小,建议删除掉图片元信息
,只保留真正有用的部分。
另外,页面中的图片,尽可能不要使用 CSS 去拉伸或者缩放,须要多大的图片,就返回多大的图,避免资源浪费。
上面介绍了 HTTP 的历史以及现阶段使用最普遍的 HTTP1 ,接下来咱们来介绍一下 HTTP2 ,看一看 HTTP2 是怎么解决 HTTP1 所遗留的问题?
首先,要搭建 HTTP2 服务,必须配套使用 HTTPS 安全策略,才能获得浏览器的支持。HTTP2 其实并无要求必须使用 HTTPS,只是人们正好认识到 HTTPS 的重要性,而 HTTP2 正好出来,就不谋而合的结合在一块儿了
。
分帧会来来以下好处:
一、二进制协议:HTTP2 的分帧层是基于帧的二进制协议,方便机器解析。
二、首部压缩:仅仅使用二进制协议还不够,HTTP2 的首部还会被深度压缩。
三、多路复用:当你在使用 HTTP2 传输连接的时候,没必要等待上一个请求结束后才进行下一个请求,请求和响应能够交织在一块儿。
HTTP2 是基于帧的协议,为了将重要的信息都封装起来,让协议的解析方能够轻松的阅读、解析并还原信息。相比之下,HTTP1 并非基于帧的,而是以文原本分隔,服务器只能根据文本换行符来拆分请求数据。
使用 HTTP1 可能会产生如下问题:
<crlf>
,有些平台采用<lf>
帧有着严格的结构格式,有了帧,处理协议的程序就能预先知道会受到什么,从而采起对应的解析方法。能够把帧理解为一个对象:
var frame = { length:'帧负载的长度', Type:'类型', Flags:'帧的标识', R:'保留位', Stream Identifer :'每一个流惟一ID', Frame Payload:'真实的帧内容' }
这样以来,实现和维护都会简单不少,不用等到一个请求完成之后才进行下一次请求,请求和响应能够交错甚至可多路复用。
流是 HTTP2 连接上独立的,双向的帧序列交换。能够将流看做在链接上的一些列帧,他们构成了单独的 HTTP 请求和响应。
一、消息:泛指 HTTP 中一个请求或一个响应。
二、流量控制:当一段接收并消费被发送的数据时,它将发出一个 WINDOW_UPDATE 帧,用来表示其更新后的处理字节的能力。
确保一个流不会影响到其余的流。
三、优先级
首先请求网页上最重要的元素,以最优的顺序获取资源,由此来优化页面性能。
提高单个资源性能的最佳方式,就是在它被用到以前就放到了浏览器的缓存里,服务器端能够主动将资源发给客户端,这多是由于它知道客户端不久后将会用到该资源。
若是服务器决定推送一个对象,会经过 PUSH_PROMISE 帧去传递将会被推送的资源。
以前说到,HTTP1 中没有对首部进行压缩,这会在每次请求中发送大量的冗余首部,而 HTTP2 则解决了这个问题。HTTP2 没有使用 gzip 压缩,而是使用 HPACK,由于 GZIP 压缩有泄漏加密信息的风险,简称 CRIME。
CRIME 原理:攻击者在请求中添加数据,观察压缩加密后的数据量,若是变小了,就证实注入的数据和请求中的其余内容有重复,进而搞清楚全部的加密数据内容。
HTTP2 的 HPACK 原理:
当客户端请求时,会根据发送的首部信息,创建一张表:
索引 | 首部名称 | 值 |
---|---|---|
62 | header1 | foo |
63 | header2 | bar |
64 | header3 | baz |
服务器端再接收到数据的时候也会建立一张与之对应的表。客户端在发送下一个请求的时候,若是首部是相同的,就不用发送 Header 头,只用发送索引号就好了,服务器端会索引去还原对应的首部信息。
以前说了这么多 HTTP2 的好处,你是否已经以为升级 HTTP2 已经火烧眉毛了呢?可是 HTTP2 页不是完美的,这一小节咱们来介绍一下 HTTP2 的一些坑。
一、关于丢包。以前说到,HTTP2 采用多路复用,可让多个请求在同一个 TCP 链接中进行传输,可是因为 HTTP2 是单连接架构,若是惟一的链接发生了丢包,全部的工做都会受到影响,这实际上是 HTTP2 中比较大的坑。
HTTP1 在请求时创建了多个链接(和浏览器相关,通常为 6 个),相对于 TCP 的初始拥塞窗口更大。当有一个链接发生丢包时,不会影响到其余请求。对比之下: HTTP2 比 HTTP1 更容易丢包。
二、关于服务器端推送。以前说到,服务器端推送能够主动给客户端推送资源,用来减小客户端发起请求数量。但是这也可能带来一个问题:若是推送的资源在客户端已经缓存过,那就是画蛇添足了,因此在作服务器端渲染时,必定要和客户端的缓存策略结合起来。
HTTP2 部署以后,以前针对于 HTTP1 的优化方案有可能就不适用了,咱们来看一下都有哪些。
在 HTTP1 中,会将一些静态资源存在多个 cdn 服务器(由于浏览器对同一个域名下的资源请求并发数有限制,通常是 6 个)。可是使用 HTTP2 以后就没必要要了,由于 HTTP2 采用多路复用,再多的资源也都可以进行并发请求。
在 HTTP1 中,咱们可会对一些小图片直接打包成 base64 格式,用来减小请求。但内联没法利用缓存优点,应具体状况具体分析。
因为多路复用的缘由,多个小图片能够并行请求,雪碧图也不是颇有必要了。
在 HTTP1 中,因为没法压缩首部,会启动一个无 cookie 的服务器专门用来存放某些静态资源,用来减小没必要要的 cookie 传输。在 HTTP2 中,首部信息会被 HPACK 算法优化,大大减小了首部字节,并且不用心增一个无 cookie 的服务器,因此建议取消掉禁用 cookie 域名的方式。
高数浏览器,之哟啊有可能就继续下载可缓存资源,并把这些资源缓存起来,这个仍是有必要。
<link rel="prefetch" href="xxx.css">
一、HTTP 是使用 TCP 做为传输层的协议,因为 TCP 是可靠的,拥塞控制的协议,在进行一次链接时,会发生三次握手,断开链接时会有 4 次挥手,因此有人提出能够用 UDP 这种简单,快速的协议去代替。
二、TLS(传输层安全协议,用来实现 HTTPS)也在不断地进行改进。在 TLS1.3 版本中 新链接只须要一次往返(目前最少是三次),若是是恢复链接,则不须要往返延时。