HTTP2协议
HTTP的1.1的现状:
http1.1过于庞大,有很多实现的细枝末节很难彻底实现。导致客户端和服务端的互用性存在问题。
http 1.1很难榨干TCP协议所能提供的所有性能。
http1.1对网络延迟非常敏感,原因是HTTP pipelining还存在很多问题。
http1.1存在线头阻塞,虽然利用HTTP pipelinling技术可以把多个http请求放到一个TCP连接中一一发送,但是客户端还是需要按照发送顺序来接收响应。如果前一个请求非常耗时,那么后续请求都会受到影响,这就是所谓的线头阻塞。
曾经为了克服延迟的操作
Spriting
将小图合并成大图,再用前端技术进行切割。但是不利于缓存,当其中一张图片发生变化的时候,整张大图都要改变。
Inlining
通过内联,把图片数据直接放到css文件中。
Concatenation
通过拼接,将多个文件合并成一个文件。
Sharding
分片将服务分散在多个服务器上,来让客户端同时和多个主机建立多条链接,来提高效率。
http2
http2的前身是SPDY。
基于TLS之上的http2协商
有两个协商协议:SPDY使用NPN,HTTP2使用ALPN。他们两个的主要区别在于谁来决定通讯协议,ALPN由服务端选择,NPN又客户端选择。基于TLS时,可以不使用Upgrade来升级,而使用TLS的一个扩展来协商。
基于非TLS的http2
会先用一次通讯,客户端给服务端发送升级请求,服务端如果支持会返回“101 Switching”作为回复,则升级成http2,但是现在还没有任何主流浏览器支持非TLS的http2。
二进制的http2协议
HTTP2是一个二进制协议。
HTTP1.1是一个基于文本的协议,但是要针对开始和结束识别起来相当复杂,而压缩以及tls加密也降低了基于纯文本实现的价值。
多路复用的流
每个单独的HTTP2链接都可以包含多个并发的流,既然如此,那么会导致各个流的数据包会被混合在一起,到那时在终点处,会根据Stream Identifier重新组装,从而得到完整的数据。
优先级和依赖性
每个流都包含一个优先级,当资源有限的时候,服务端会根据优先级选择发送哪些流。
优先级和依赖关系可以在传输过程中被动态的改变。这样当用户在滚动一个全是图片的页面的时候,浏览器就能指定哪些图片拥有更高的优先级。或者在你切换便签页的时候,浏览器可以提升新切换到页面所包含流的优先级。
头压缩
http的头变得越来越大,但是存在大量一致的东西,这些东西值得被压缩。用的压缩算法是HPACK,更加安全。
重置
增加重置Content-Length的方法,通过RST_STREAM帧,而不是需要重新建立TCP请求。
服务器推送
当客户端需要资源X的时候,服务器知道它肯定还需要资源Y,就把Y也推送给客户端,这样客户端在想要Y资源的时候,会直接从缓存拿取。
流量控制
对于每个流来说,两端都必须告诉对方自己还有足够的空间来处理新的数据,而在该窗口被扩大前,另一端只能发这么多。
HTTP2协议详细内容
- http/2通过定义一个优化的HTTP语义到底层链接的映射来解决一条连接只能一次请求,并可以高效地使用HTTP报头,还允许请求具有优先级,让更重要的请求更快地完成,进一步提高了性能。
- http2支持http1.1的所有核心功能(持久连接,在响应后不关闭TCP通道,新增首部字段Host,客户端指名要访问的主机,使得服务端可以在统一域名的不同主机之间实现多个虚拟web站点,新增http pipelining,允许(GET,HEAD)同时发送等)
- http2中基础的协议单元是帧,每个不同类型的帧都服务于不同的目的。比如HEADERS和DATA帧构成了基本的HTTP请求和应答。
- 请求的多路复用即在每个HTTP请求/应答在各自的流中完成数据交换,由于每个流之间都是相互独立的,因此即使请求和应答被阻塞或者速度很慢都不会影响各自流中的处理流程。
- 在请求者请求url之前,需要先确定上游服务器是否支持HTTP2
- http的版本协议有两种标识符:h2代表建立在TLS上的HTTP2通讯,h2c代表不适用TLS协议。存在Upgrade。
所有的帧都以一个9字节的报头开始, 后接变长的载荷:
+-----------------------------------------------+
| Length (24) |
+---------------+---------------+---------------+
| Type (8) | Flags (8) |
+-+-------------+---------------+-------------------------------+
|R| Stream Identifier (31) |
+=+=============================================================+
| Frame Payload (0...) ...
+---------------------------------------------------------------+
-
Length
: 载荷的长度, 无符号24位整型. 对于发送值大于2^14 (长度大于16384字节)的载荷, 只有在接收方设置SETTINGS_MAX_FRAME_SIZE
为更大的值时才被允许注: 帧的报头9字节不算在length里.
Type
: 8位的值表示帧类型, 决定了帧的格式和语义. 协议实现上必须忽略任何未知类型的帧.Flags
: 为Type保留的bool标识, 大小是8位. 对确定的帧类型赋予特定的语义, 否则发送时必须忽略(设置为0x0).R
: 1位的保留字段, 尚未定义语义. 发送和接收必须忽略(0x0).Stream Identifier
: 31位无符号整型的流标示符. 其中0x0作为保留值, 表示与连接相关的frames作为一个整体而不是一个单独的流.
stream标识符:客户端使用奇数,服务端使用偶数。