HTTP2详解
Posted 张孟浩_jay
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HTTP2详解相关的知识,希望对你有一定的参考价值。
HTTP2简介
HTTP2是对HTTP1.1的升级,对HTTP1.1性能问题进行了优化,主要从以下两个方面来优化:
1、头部压缩
HTTP1.1主要是对Body进行压缩,而头部却没有压缩。HTTP2通过HPACK算法对头部进行压缩,减少了传输时间。
2、队头阻塞
HTTP1.1使用的是TCP协议,并且为了节省资源,采用了长连接,长连接引入了队头阻塞的问题。HTTP2引入了流和帧,解决了HTTP层面上的队头阻塞。
HTTP2报文结构详解
1、二进制 替换 文本
HTTP1.1采用的是文本描述,也就是通过ASCII文本进行传输,采用文本描述的好处是调试程序方便,能够直接看出数据包中的数据情况。
而HTTP2使用的二进制来进行传输,用01串来描述数据,调试和查看数据的具体含义就不填方便了。但是这种二进制传输计算机解析方便,体积小,性能高。
举个例子,比如之前需要传递对应的文本值来表示对应的选择,而二进制通过二进制编码就能知道编码对应的选择,一个二进制编码对应着一个文本值。 一个二进制编码肯定比文本占用的空间小。
2、HTTP2将HTTP1中数据包分解为了帧
将HTTP1.1的数据包分为HEADERS帧和DATA帧,属于是化整为零,为的就是多路复用,具体原理我们下边再说。
HTTP2连接过程
连接前言
当TCP三次握手成功后,客户端需要向服务器发送一个连接前言。
连接前言是一个HTTP1.1报文,是一个ASCII文本,里面记录着一个magic字符串,当服务器接收到这个请求后,服务器就知道客户端想要使用HTTP2协议。
头部压缩
确定了HTTP2连接后,就开始准备发送HTTP2请求了。
首先就是发送HEADERS 帧,
HTTP1.1中对Body进行GZIP等压缩方式,但是对于头部却没有采取任何办法。
HTTP2采用了 HPACK 算法来压缩,HPACK 中客户端和服务器都要维护一个索引表。
如上图所示,索引表中维护了头部中Key-Value的对应关系和索引下标。
到时候,HTTP2请求中头部不用再发送Key-Value了,直接发送对应的索引下标就可以了。
上述的索引表是一个静态的表,记录着常用的头字段。HTTP的起始行中记录了Method、StatusCode等信息,也被记录到了索引表中。
有的HTTP2头部有着特殊的头部字段,所以HPACK又在静态表的尾部开始维护一个动态记录。当第一次发送索引表中不存在的Key-Value的时候,会使用实际数据发送,客户端和服务器对应的索引表会对其缓存,等到下一次发送的时候,就可以直接发送索引下标了。
所以说,HTTP2通过HPACK算法,将每次发送Key-Value替换成了发送一个下标,极大的减少了HTTP2头部的数据量,传输效率极大的提高了。
二进制帧
HTTP2将之前的head+body的一个数据包分为了 HEADER帧 和 若干个 DATA帧
格式如下图所示:
1、帧长度
帧的总长度,应用程序按照长度来读取
2、帧类型
HTTP2中有 数据帧、控制帧等类别,控制帧有着更高的传输优先权
3、标志位
8个bit,可以代表8个状态,比如END_HEADERS代表是否头数据传输结束、END_STREAM表示单方面传输数据结束
4、流标识符
帧属于哪个流,每个HTTP包传输都是一个虚拟流,通过流标识符才能将前后发送的帧重组为一个完整的数据包。
5、实际传输的数据
HTTP2发送过程
HTTP2利用帧+流的方式解决了HTTP1中的队头阻塞问题。
HTTP1中每个HTTP包复用一个TCP连接,每次只能等到前一个HTTP响应后才能发送后一个HTTP请求,如果前一个HTTP响应阻塞的话,后面的HTTP请求都会跟着阻塞,这就是队头阻塞问题。
HTTP2也是利用的长连接,多个HTTP请求复用一个TCP连接。
但是HTTP2将每个HTTP请求都看作一个流,将HTTP数据包分解为多个帧,包括HEADER帧和DATA帧。每个帧都对应着一个流标识号。
多个HTTP请求之间的发送是乱序的,但是每个HTTP请求中的帧的发送是有序的。
虽然多个HTTP请求之间的发送请求是乱序的,但是可以基于流标识符来进行重组,一个流标识符对应着一个HTTP请求。
流标识符不能复用,是自动递增的,客户端使用的是奇数,服务器使用的偶数。
这就解决了队头阻塞问题。
以上是关于HTTP2详解的主要内容,如果未能解决你的问题,请参考以下文章