HTTP 2
推荐阅读:https://segmentfault.com/a/1190000011172823?utm_source=tag-newest
进来支持 HTTP 2 的网站越来愈多了,这是一个很好的趋势。虽然 HTTP 2 的 RFC 写得很厚,但是总的来说可以总结为以下几点:
1. 通过 TCP 多路复用,降低延迟
3. 强制使用 TLS,保证安全性问题
4. 头部压缩
5. Server Push
多路复用
简单的来说,就是所有HTTP请求都走同一个TCP。
在 HTTP 1.1
实现并发,一般是通过建立多个TCP连接来实现,现代浏览器支持最大并发数一般达到6~10(chrome 最多6个)。
虽然 HTTP 1.1 规范给出来 Pipelining,但是受限于出现的一些问题,浏览器都是默认关闭的 :
A client that supports persistent connections MAY "pipeline" its requests (i.e., send multiple requests without waiting for each response).
A server MUST send its responses to those requests in the same order that the requests were received.
一个支持持久连接的客户端可以在一个连接中发送多个请求(不需要等待任意请求的响应)。收到请求的服务器必须按照请求收到的顺序发送响应。
因为 HTTP 1.1 是基于文本的,所以并不能区分Response对应的是哪个请求,因此,只能规定必须按顺序返回响应,这样就会有一个“队首阻塞”的问题。
即使靠后接受到的请求,已经处理完毕,也得需要前面的请求处理好了,才能往回响应。
这样的话,实际TCP只能串行响应请求。
在 HTTP 2
改变 HTTP 基于文本的特性,变成基于流。
每一个请求都是一个流,每个流由多个帧组成,可以简单理解成每一次传输就是一帧。
帧头会有标识,来表示这一帧是属于那个流(请求)的。
这样的话,一个TCP连接就不会因为一个HTTP请求响应慢,而阻塞了,因此对于并发,我们完全可以用一个TCP请求就可以了。
我们来看看下面的图:
HTTP/1.1通过pipelining管道技术实现一次性发送多个请求,以期提高吞吐和性能,如上图中的序列2。
如果,第一个请求被堵塞了,则后面的请求即使处理完毕了,也需要等待,如上图中的序列3。
那么,HTTP/2是怎么解决这个问题的呢?
那就是数据分帧:多个请求复用一个TCP连接,然后每个request-response都被拆分为若干个帧发送,这样即使一个请求被阻塞了,也不会影响其他请求,如上图序列4所示。
PS:值得注意的是“多路复用”,仅仅解决了 HTTP 1.1 在应用层上的限制(不允许响应数据交错到达),而如果 HTTP 的传输层仍然采用TCP的话,TCP在传输层的“队首阻塞”也仍然存在(就是丢包的时候,需要后续的包等待丢的包重传到达。)如果这样的话,这个丢包的影响,在HTTP 2 甚至比 HTTP 1.1 更严重,因为只有一个 TCP连接,而这个 TCP 发生了 对首阻塞”。
推荐阅读:https://www.zhihu.com/question/65900752/answer/255085226
https://www.jianshu.com/p/11c2614ef3f2
TLS 和 SSL
对于 HTTP 2 浏览器会强制使用TLS(实际上现在我们用的都是TLS,但是由于历史上的习惯,我们都叫它做SSL)
SSL是Netscape开发的专门用户保护Web通讯的,目前版本为3.0。最新版本的TLS 1.0是IETF(工程任务组)制定的一种新的协议,它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本。两者差别极小,可以理解为SSL 3.1,它是写入了RFC的。
头部压缩
1. 使用 HPACK 压缩格式,对 header 进行压缩
2. 双方维护一份头部索引表,如果是已经发送过的相同的头部,用索引号来代替(例如cookie只需要发送一次,如果没有发生变化,下次用索引号代替)
服务端 Push
如果服务端接收到客户端主请求,能够“预测”主请求的依赖资源,在响应主请求的同时,主动并发推送依赖资源至客户端。客户端解析主请求响应后,可以”无延时”从本地缓存获取依赖资源, 减少访问延时, 提高访问体验,也加大了链路的并发能力。
server push 和 websocket 的区别:https://blog.csdn.net/axman/article/details/79875463