HTTP/1.x 队头阻塞、域名分片、管道机制、
- HTTP/1.x TCP数据包、文本传输
HTTP/1.x 是通过文本进行传输的;
HTTP消息放入一个个TCP数据包中传送,每个包有固定的大小,HTTP消息太多,就需要分成多个TCP数据包传输。每一个TCP数据包包都有一个编号(sequence number简称seq),接收方可以按照这个编号顺序还原消息。万一丢包,也可以知道丢失的是哪一个包。
- HTTP/1.x 的连接,请求是序列化的,
客户端的第二个请求要等到第一个请求应答之后才能发送;
- HTTP/1.1 管道机制
HTTP/1.1 引入管道机制,客户端发送第一个请求后,无需等到第一个请求应答即可发送第二个请求;但第二个请求的应答需要等到第一个请求应答之后发送;
- 队头阻塞
HTTP/1.x 等待应答即会引起队头阻塞 HTTP/2 也存在队头阻塞问题
- HTTP/1.x 域名分片
为解决HTTP/1.x的队头阻塞问题,浏览器为每个域名建立多个连接,以实现并发请求。一般浏览器为每个域名建立6条连接。如果想要获取更多的连接,则可以使用“域名分片”的技术,及创建多个域名。
- HTTP/1.1 为什么需要顺序应答呢?
一个TCP数据包可能包含两个HTTP请求消息。 TCP数据包的编号只能还原一个HTTP请求的消息,并不能区分每个包属于哪一个http请求。
HTTP/2 二进制帧和流
HTTP/2 为了解决HTTP1.x的队头阻塞问题,引入了二进制帧和流传递数据。 HTTP/2将一个HTTP请求分成两个帧,headers帧和data帧, 并且采用二进制编码。 一个TCP连接上可以有任意数量的流。 一个HTTP请求或相应职能在一个流上发送。 流是建立在TCP连接上的双向字节流;一个HTTP的请求和响应在一个流上发送。 一个流可以承载一个或多个帧。 顾HTTP/2 是无序发送数据的;请求和响应都不需要顺序发送。
HTTP/1.x 短连接、长连接
- 短连接
一个TCP连接对应一个HTTP请求
- 长连接
一个TCP连接对应多个HTTP请求; 节省了TCP三次握手四次挥手的时间; 一个HTTP请求对应1个或者多个TCP数据包; 多个HTTP请求多个TCP数据包是串行连续且有序的进行传输;
如果一个连接不会断开,那么多个请求之间如何进行区分?
- Content-length Content-length表示实体内容的长度。当服务器能明确知道返回内容的长度时,可以设置content-length,浏览器通过这个字段来判断当前请求的数据是否已经全部接受。
- transfer-encoding 当服务器无法知道实体内容的长度时,就可以通过指定transfer-encoding:chunked来告知浏览器当前的编码是将数据分成一块一块传递的。还可以指定transfer-encoding:gzip, Chunked表明实体内容不仅是gzip压缩的,还是分块传递的。最后,当浏览器接收到一个长度为0的chunked时,知道当前请求内容已全部接收。
HTTP/2 多路复用
同一域名的所有HTTP请求公用一个TCP连接。
当客户端同时向服务端发起多个请求,那么这些请求会被分成一个个的帧,所有帧都会在一个TCP链路中无序的传输,同一个请求的帧的stream Identifier 都是一样的。当帧到达服务器之后,就可以根据stream Identitifier 来重新组合得到完整的请求。
HTTP/2 头部压缩(HPACK)
在http1.x协议中,每次请求都会携带header数据,而类似User-Agent、Accept-Language等信息在每次请求过程中几乎是不变的,那么这些信息在每次请求过程中就变成了浪费。所以,http2中提出了一个HPACK的压缩方式,用于减少http header在每次请求中消耗的能量。
HPACK压缩的原理如下:
客户端和服务端共同维护一个【静态字典】,字典中每行3列,类似下表:
| index | header name | header value |
|---|---|---|
| 2 | :method | GET |
| 3 | :method | POST |
当请求的header头部中包含:header:GET,客户端在发送请求的时候,会直接发送静态字段中对应的index值,在这里也就是2。服务端在接收到请求的时候,去寻找静态字典中index=2对应的header name 和 header value,就明白了客户端发起了一个GET请求。
客户端和服务端都必须维护一套一样的静态字典, 这里给出了完整的静态字典,客户端和服务端都会遵守这套静态字典。
HTTP/2 服务器推送
服务器推送指的是服务器主动向客户端推送数据。