参考
HTTP发展史
- HTTP/0.9 - 单行协议
- 问世于1990年,那时的HTTP非常简单: 只支持GET方法; 没有首部; 只能获取纯文本
- HTTP/1.0 - 搭建协议的框架
- 1996年,HTTP正式被作为标准公布,版本为HTTP/1.0。1.0版本增加了首部、状态码、权限、缓存、长连接(默认短连接)等规范,可以说搭建了协议的基本框架。
- HTTP/1.1 - 进一步完善
- 1997年,1.1版本接踵而至。1.1版本的重大改进在于默认长连接; 强制客户提供Host首部;管线化;Cache-Control、ETag等缓存的相关扩展
- 注: Etag和Last-Modified同时存在,以Etag为主
- 1997年,1.1版本接踵而至。1.1版本的重大改进在于默认长连接; 强制客户提供Host首部;管线化;Cache-Control、ETag等缓存的相关扩展
【HTTP/1.0的缺陷】:
- 连接无法复用: 一个连接对应一次握手
- 队头阻塞: 前面一个连接未完成,后面的连接无法进行
对于问题1, HTTP/1.1新增了一个connection: keep-alive
,使连接完成后不断开.
目前存在的问题
我们先来看看HTTP发展到1.1存在的问题:
- 线头阻塞: TCP连接上只能发送一个请求,前面的请求未完成前,后续的请求都在排队等待.
- 多个TCP连接:
- 虽然HTTP/1.1管线化可以支持请求并发,但是浏览器很难实现,chrome、firefox等都禁用了管线化.所以1.1版本请求并发依赖于多个TCP连接,建立TCP连接成本很高,还回存在慢启动的问题.
- 头部冗余,采用文本格式
- HTTP/1.X版本是采用文本格式,首部未压缩,而且每一个请求都会带上cookie、user-agent等完全相同的首部
- 客户端需要主动请求
HTTP/2.0中的一些重大改进
HTTP2性能提升的核心就在于二进制分帧层。HTTP2是二进制协议,他采用二进制格式传输数据而不是HTTP/1.x的文本格式
-
1.1响应是文本格式,而2.0把响应划分为两个帧
- HEADERS frame: 首部
- DATA frame: 消息负载
-
也就是说: 一条HTTP响应,划分为两个帧来传输,并且采用二进制来编码
- 流(Stream): 已经建立TCP连接上的双向字节流,可以承载一个或多个消息
- 消息(Message): 一个完整的HTTP请求或响应,由一个或多个帧组成。特定消息的帧在同一个流上发送,这意味着一个HTTP请求或响应只能在一个流上发送.
- 帧(Frame): 通信的基本单位。 一个TCP连接上可以由任意数量的流
多路复用
HTTP/2.0让所有的通信都在一个TCP连接上完成,真正实现了请求的并发.
HTTP/2.0建立一个TCP连接,一个连接上面可以有任意多个流(stream),消息分割成一个或多个帧在流里面传输。帧传输过去以后,再进行重组,形成一个完整的请求或响应。这使得所有的请求或响应都无法阻塞。
头部压缩
在1.X版本中,首部用文本格式传输,通常会给每个传输增加500~800字节的开销。大多数请求的首部字段是相同的(如cookie、user-agent等)。
HTTP2为此采用HPACK压缩格式来压缩首部,头部压缩需要在浏览器和服务器之间:
- 维护一份相同的静态字典,包含常见的头部名称,以及常见的头部名称和值的组合
- 维护一份相同的动态字典,可以动态的添加内容
- 通过静态Huffman编码对传输的首部字段进行编码
HTTP/2.0的静态字典,部分:
Index | Header Name | Header Value |
---|---|---|
1 | :authority | |
2 | :method | GET |
3 | :method | POST |
4 | :path | / |
5 | :path | /index.html |
6 | :schema | http |
7 | :schema | https |
8 | :status | 200 |
9 | :status | 204 |
所以我们在传输首部字段的时候,例如要传输method:GET
,那我们只需要传输静态字典里面method: GET
对应的索引值就可以了,一个字节搞定.
像user-agent、cookie
这种字典里面只有首部名称而没有值的首部,第一次传输需要user-agent
在静态字典中的索引以及他的值,值会采用Huffman编码来减小体积
第一次传输过user-agent
之后,浏览器和服务器就会把它添加到自己的动态字典中。后续传输就可以传输索引了,一个字节
服务器推送技术
-
服务器推送: 使得服务器可以预测客户端需要的资源,主动推送到客户端
-
例如: 客户端请求index.html,服务器端能够额外推送
script.js
和style.css
.原理:- 客户端发送请求时,服务器能够分析这个页面所依赖的其他资源,主动推送到客户端的缓存
- 当客户端收到原始网页的请求时,它需要的资源已经位于缓存