HTTP/2详解

HTTP/2详解

简介

HTTP/2主要是为了解决现HTTP 1.1性能不好的问题才出现的。当初Google为了提高HTTP性能,做出了SPDY,它就是HTTP/2的前身,后来也发展成为HTTP/2的标准。

HTTP/2兼容HTTP 1.1,例如HTTP Method,Status code,URI以及大部分Header Fields。

二进制分帧

HTTP/2 所有性能增强的核心在于新的二进制分帧层,它定义了如何封装 HTTP 消息并在客户端与服务器之间传输。HTTP/1.x 协议以换行符作为纯文本的分隔符,而 HTTP/2 将所有传输的信息分割为更小的消息和帧,并采用二进制格式对它们编码

HTTP/2 的三个概念:

  • 数据流:已建立的连接内的双向字节流,可以承载一条或多条消息。流可以承载双向消息,每个流都有一个唯一的整数ID。
  • 消息:与逻辑请求或响应消息对应的完整的一系列帧
  • 帧:HTTP/2 通信的最小单位,每个帧都包含帧头,至少也会标识出当前帧所属的数据流

二进制协议解析起来更高效。 HTTP / 1 的请求和响应报文,都是由起始行,首部和实体正文(可选)组成,各部分之间以文本换行符分隔。HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。

image-20211205213656388

在 HTTP/1.x 中,如果客户端要想发起多个并行请求以提升性能,则必须使用多个 TCP 连接,HTTP/2 中新的二进制分帧层突破了这些限制,实现了完整的请求和响应复用:客户端和服务器可以将 HTTP 消息分解为互不依赖的帧,然后交错发送,最后再在另一端把它们重新组装起来。

HTTP/2 中,同域名下所有通信都在单个连接上完成,该连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,根据帧首部的流标识可以重新组装。

简单来说,所有通信都在一个 TCP 连接上完成(复用,当然如果由于解码、编码都在一个CPU上完成,为了追求效率也可以用多个连接),此连接可以承载任意数量的双向数据流。每个数据流都有一个唯一的标识符和可选的优先级信息,用于承载双向消息。每条消息都是一条逻辑 HTTP 消息(例如请求或响应),包含一个或多个帧。来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装。

多路复用

多路复用,代替原来的序列和阻塞机制。所有就是请求的都是通过一个 TCP连接并发完成。 HTTP 1.x 中,如果想并发多个请求,必须使用多个 TCP 链接,且浏览器为了控制资源,还会对单个域名有 6-8个的TCP链接请求限制

在 HTTP/2 中,有了二进制分帧之后,HTTP /2 不再依赖 TCP 链接去实现多流并行了,在 HTTP/2中:

  • 同域名下所有通信都在单个连接上完成。
  • 单个连接可以承载任意数量的双向数据流。
  • 数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。

这一特性,使性能有了极大提升:

  • 同个域名只需要占用一个 TCP 连接,消除了因多个 TCP 连接而带来的延时和内存消耗。
  • 单个连接上可以并行交错的请求和响应,之间互不干扰。
  • 在HTTP/2中,每个请求都可以带一个31bit的优先值,0表示最高优先级, 数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。

头部压缩

在 HTTP/1.x 中,此元数据始终以纯文本形式,通常会给每个传输增加 500–800 字节的开销。如果使用 HTTP Cookie,增加的开销有时会达到上千字节。

1.利用霍夫曼编码,可以在传输时对各个值进行压缩

2.利用之前传输值的索引列表,通过传输索引值的方式对重复值进行编码

霍夫曼编码:

image-20211205214253866

image-20211205214409420

HTTP头压缩需要在HTTP/2 Client和服务端之间:

  • 维护一份相同的静态表(Static Table),包含常见的头部名称,以及特别常见的头部名称与值的组合;
  • 维护一份相同的动态表(Dynamic Table),可以动态地添加内容;
  • 基于静态哈夫曼码表的哈夫曼编码(Huffman Coding);

在编码时,它们直接用一个index编号代替,例如:method:GET是2

使用静态表、动态表、以及Huffman编码可以极大地提升压缩效果。对于静态表里的字段,原来需要N个字符表示的,现在只需要一个索引即可,对于静态、动态表中不存在的内容,还可以使用哈夫曼编码来减小体积。

服务器推送

服务端可以在发送页面HTML时主动推送其它资源,而不用等到浏览器解析到相应位置,发起请求再响应。例如服务端可以主动把JS和CSS文件推送给客户端,而不需要客户端解析HTML时再发送这些请求。

服务端可以主动推送,客户端也有权利选择是否接收。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送RST_STREAM帧来拒收。主动推送也遵守同源策略,服务器不会随便推送第三方资源给客户端。

在HTTP 1.1里,在同一个 TCP 连接里面,上一个回应(response)发送完了,服务器才能发送下一个,但在HTTP/2里,可以将多个回应一起发送。

image-20211205215045068

image-20211205215058405


   转载规则


《HTTP/2详解》 朱林刚 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
Go容器 Go容器
Go容器Go容器数组数组的长度不可变 var name [size]T //声明时需要指定大小 var students [3]int //也可以通过指针操作数组 students2 := new([3]int) fmt.Pri
2021-12-08
下一篇 
Go 三个点...语法使用 Go 三个点...语法使用
Go 三个点…语法使用变长的函数参数函数有多个不定参数的情况,可以接受多个不确定数量的参数。 如果最后一个函数参数的类型的是…T,那么在调用这个函数的时候,我们可以在参数列表的最后使用若干个类型为T的参数。这里,…T在函数内部的类型实际是
2021-12-04
  目录