共计 2194 个字符,预计需要花费 6 分钟才能阅读完成。
更多内容,欢迎关注微信公众号:全菜工程师小辉。公众号回复关键词,领取免费学习资料。
HTTP 版本简史
- HTTP/0.9:
(1991 年)基于 GET 请求的文本传输协议
- HTTPS:
(1994 年)安全的 HTTP 传输协议
- HTTP/1.0:
(1996 年)增加 HTTP 头、扩展 PUT、POST 等方法
- HTTP/1.1:
(1999 年)长连接、流水线支持,最广泛使用的 HTTP 传输协议
- SPDY:
(2012 年)针对 HTTP 的增强,工作在 SSL 层之上、HTTP 层之下
- HTTP/2:
(2015 年)二进制格式、多路复用、服务器“推送”、头部压缩
HTTP/ 2 的开发基于 SPDY 进行跃进式改进在诸多修改中,最显著的改进在于,HTTP/ 2 使用了一份经过定制的压缩算法,基于霍夫曼编码,以此替代了 SPDY 的动态流压缩算法,以避免对协议的 Oracle 攻击——这一类攻击以 CRIME 为代表。此外,HTTP/ 2 禁用了诸多加密包,以保证基于 TLS 的连接的前向安全(参考 Wiki)
2015 年 9 月,Google 宣布了移除对 SPDY 的支持,拥抱 HTTP/2,并将在 Chrome 51 中生效。
HTTP/ 2 和 HTTP/1.1 的速度对比,可以点击查看下面两个网页:
https://http2.akamai.com/demo
http://http2.cdnpe.com/index.html
相比 HTTP/1.1 的改进
1. 解决串行的文件传输和队头阻塞问题
在 HTTP/1.1 中,当请求 a 文件时,b 文件只能等待,等待 a 连接到服务器、服务器处理文件、服务器返回文件,这三个步骤。我们假设这三步用时都是 1 秒,那么 a 文件用时为 3 秒,b 文件传输完成用时为 6 秒,依此类推。
此项计算有一个前提条件,就是浏览器和服务器是单通道传输
在 HTTP/1.1 的协议中,由于传输的 request 和 response 都是基本于文本的,这样就会引发一个问题:所有的数据必须按顺序传输,比如需要传输:hello,只能从 h 到 o 一个一个的传输,不能并行传输,因为接收端并不知道这些字符的顺序,所以并行传输在 HTTP1.1 是不能实现的。
此外,队头阻塞问题在 HTTP/ 2 终于得到解决。
队头阻塞问题:每个 TCP 连接同时只能处理一个请求 – 响应,浏览器按 FIFO 原则处理请求,如果上一个响应没返回,后续请求 – 响应都会受阻。为了解决此问题,出现了 管线化 – pipelining 技术,但是管线化存在诸多问题,比如第一个响应慢还是会阻塞后续响应、服务器为了按序返回相应需要缓存多个响应占用更多资源、浏览器中途断连重试服务器可能得重新处理多个请求、还有必须客户端 – 代理 – 服务器都支持管线化。
解决方案
HTTP/ 2 引入二进制数据帧和流的概念,其中帧对数据进行顺序标识,这样浏览器收到数据之后,就可以按照序列对数据进行合并,而不会出现合并后数据错乱的情况。同样是因为有了序列,服务器就可以并行的传输数据,这就是流所做的事情。
此外,HTTP/ 2 里的每个 stream 都可以设置依赖 (Dependency) 和权重,可以按依赖树分配优先级,解决了关键请求被阻塞的问题
2. 解决连接数过多。
我们假设 Apache 设置了最大并发数为 300,因为浏览器限制,浏览器发起的最大请求数为 6,也就是服务器能承载的最高并发为 50,当第 51 个人访问时,就需要等待前面某个请求处理完成。
解决方案
我们来看一下,HTTP/ 2 的多路复用是如何解决的。
HTTP/ 2 对同一域名下所有请求都是基于流,也就是说同一域名不管访问多少文件,也只建立一路连接。同样 Apache 的最大连接数为 300,因为有了这个新特性,最大的并发就可以提升到 300,比原来提升了 6 倍!
此外,HTTP/ 2 支持服务器推送。
浏览器发送一个请求,服务器主动向浏览器推送与这个请求相关的资源,这样浏览器就不用发起后续请求。
这主要是针对资源内联做出的优化,相较于 HTTP/1.1 资源内联的优势:
- 客户端可以缓存推送的资源
- 客户端可以拒收推送过来的资源
- 推送资源可以由不同页面共享
- 服务器可以按照优先级推送资源
3. Header 内容冗余问题。
Header 内容内容多,而且每次请求 Header 不会变化太多,没有相应的压缩传输优化方案
解决方案
使用 HPACK 算法来压缩首部内容。
升级之后可以节省的成本
- JS 文件的合并
我们现在优化的一个主要方向就是尽量的减少 HTTP 的请求数,对我们工程中的代码,研发时分模块开发,上线时我们会把所有的代码进行压缩合并,合并成一个文件,这样不管多少模块,都请求一个文件,减少了 HTTP 的请求数。但是这样做有一个非常严重的问题:文件的缓存。当我们有 100 个模块时,有一个模块改了东西,按照之前的方式,整个文件浏览器都需要重新下载,不能被缓存。现在我们有了 HTTP/ 2 了,模块就可以单独的压缩上线,而不影响其他没有修改的模块。根据上面讲的原理,我们尽可能将资源细粒化,文件分解地尽可能散,不用担心请求数多
雪碧图,文件合并同理可以弃用
- 多域名提高浏览器的下载速度
之前我们有一个优化就是把 css 文件和 js 文件放到 2 个域名下面,这样浏览器就可以对这两个类型的文件进行同时下载,避免了浏览器 6 个通道的限制,这样做的缺点也是明显的:
1.DNS 的解析时间会变长。
2. 增加了服务器的压力。
有了 HTTP/ 2 之后,请不要使用域名分片。
更多内容,欢迎关注微信公众号:全菜工程师小辉。公众号回复关键词,领取免费学习资料。