http/2

151 阅读7分钟

HTTP/2

是一种改进的 HTTP 协议,相比于 HTTP/1.x ,使用了更高效的二进制协议、通过压缩算法减少请求头中的数据传输、解决了http/1.x的队头阻塞问题、提高了tcp连接利用率、支持服务端主动推送数据。

HTTP/2 的主要特性包括:

二进制协议:

HTTP/2 使用二进制格式进行通信,而 HTTP/1.x 使用文本协议。二进制协议更高效,能够减少解析和处理的复杂性。请求被分解成多个二进制格式的帧(frames)来传输。比如有HEADERS帧专门用于承载头部信息、DATA帧用来承载请求体中的实际数据内容等。这些帧有着特定的二进制结构,包含帧长度、帧类型、标志位、流标识符等部分,通过这样的结构计算机可以快速、准确地对其进行解析和处理。

头部压缩:

HTTP/2 使用 HPACK 算法对 HTTP 请求和响应的头部进行压缩,从而减少了传输的数据量。采用头部压缩(Header Compression)机制,运用如HPACK算法对头部信息进行压缩。它会基于之前传输过的头部信息以及头部字段的常见规律等进行动态的、有针对性的压缩。

例如,对于多个请求中重复出现的头部字段,服务器和客户端可以通过建立的索引等方式,只传输字段对应的索引编号等少量信息来替代完整的字段文本内容,减少了需要传输的数据量,同时在解析时,也能根据预先约定的压缩规则快速还原出完整的头部信息进行后续处理,提升了整体的请求解析效率以及节省了网络带宽。

多路复用:

HTTP/2 允许在一个连接上同时发送多个请求和响应,而不需要为每个请求建立独立的连接。这有效减少了连接的数量,减少了延迟。

服务器推送:

服务器可以在客户端请求之前主动推送资源到客户端,这有助于提高加载速度,尤其是当客户端可能会请求这些资源时。

流量控制:

HTTP/2 引入了更复杂的流量控制机制,允许客户端和服务器更有效地管理传输中的数据流量,避免网络阻塞。

请求优先级:

HTTP/2 允许客户端指定请求的优先级,服务器可以根据优先级来处理请求,从而提升关键资源的加载速度。

一个请求如何分解为帧?

请求行和请求头被分解为帧类型为headers的帧,请求体被分解为data类型的帧。还有其它类型的帧数。数据帧有固定的格式。解析时按固定格式解析数据帧即可。

头部压缩减少传输的数据是什么?

http/2预先定义了静态表,存储着请求头中的常用值,像 :method(请求方法字段,常见的如 GET、POST 等)、:scheme(协议方案,如 https)。每个值对应一个编号,用编号替代常用值,减少数据传输。除此之外还有动态表,动态表存储着不在静态表中但是请求中多次出现的值,同样使用编号替代。

能够在同一个TCP连接上同时发起多个请求并且接收多个响应,是如何做到的?

HTTP/2 能够在同一个 TCP 连接上同时发起多个请求并且接收多个响应,主要依靠二进制分帧层、多路复用以及流标识符等关键机制协同实现。

一、二进制分帧层

HTTP/2 在应用层(HTTP)和传输层(TCP 等)之间引入了二进制分帧层。这个分帧层将所有传输的数据分割为更小的帧(frames),并采用二进制格式进行编码。例如,一个 HTTP 消息(无论是请求还是响应)会被分解成多个不同类型的帧,常见的帧类型有 HEADERS 帧(承载头部信息)、DATA 帧(承载消息主体内容)等。

这种二进制格式的帧相比 HTTP/1 以文本格式传输数据有诸多优势:

解析高效性:计算机对二进制数据的解析速度更快、出错概率更低,便于快速准确地处理接收到的数据,为后续在同一个连接上处理多个请求和响应奠定了基础。

灵活分割性:可以根据需要灵活地把数据分割成合适大小的帧,便于在网络中传输以及接收端的重组和处理,不像 HTTP/1 那样以相对固定的报文格式传输,缺乏灵活性。

二、多路复用机制

多路复用(Multiplexing)是实现在同一个 TCP 连接上并发处理多个请求和响应的核心机制。请求与响应的独立数据流:在 HTTP/2 中,每个请求和它对应的响应构成一个独立的数据流(Stream)。例如,当客户端同时发起获取网页图片、脚本文件、样式表文件等多个不同的请求时,每个请求及其响应都分别是一个独立的数据流,它们之间互不干扰。这些数据流可以在同一个 TCP 连接上并行地进行发送和接收操作。

消除队头阻塞:与 HTTP/1 不同,HTTP/2 不存在 “队头阻塞”(Head-of-line blocking)问题。在 HTTP/1 中,多个请求在同一个 TCP 连接上是按顺序依次处理的,如果前面的请求出现延迟(比如等待服务器响应或者网络传输缓慢等原因),后面的请求就只能排队等待,无法并行处理。而 HTTP/2 的多路复用机制允许各个数据流的帧可以交错地在 TCP 连接上传输,不管某个数据流中的帧是否传输延迟,其他数据流的帧都可以正常传输,不会受到阻塞,极大地提高了网络连接的利用率以及请求响应的处理效率。

三、流标识符(Stream Identifier)

流标识符在整个多路复用过程中起着关键的分拣和关联作用。

帧的归属标识:每个帧都会带有一个 31 位的流标识符,通过这个标识符就能区分开不同请求或响应对应的帧。比如,客户端发起了三个不同的请求,分别对应流标识符为 1001、1002、1003 的三个数据流,那么这些请求对应的 HEADERS 帧、DATA 帧等所有相关帧都会带有各自对应的流标识符。服务器接收到这些帧后,依据流标识符就能准确知道该帧属于哪个具体的请求或响应数据流,进而进行相应的处理,比如将属于流标识符为 1001 的请求对应的帧的信息提取出来,按照 HTTP/2 的规则解析并处理这个请求,然后返回对应的响应,响应的帧同样也带有流标识符 1001,客户端收到后就能识别出这是自己发起的那个请求的回复。

并行处理保障:正是借助流标识符,服务器和客户端能够在同一个 TCP 连接上同时处理多个请求和响应的各种帧,实现并行操作。各个数据流的帧在网络中交错传输,依靠流标识符进行准确的分拣和组装,就如同给每个请求响应 “包裹” 都贴上了独特的 “标签”,使得它们能在同一个 “运输通道”(即 TCP 连接)中有序又高效地 “运输”(传输)和被处理。

总结

通过二进制分帧层将数据分割为便于处理的帧,利用多路复用机制创建独立且可并行处理的数据流,再借助流标识符准确区分和关联各个数据流对应的帧,HTTP/2 成功实现了在同一个 TCP 连接上同时发起多个请求并且接收多个响应,极大地提升了网络传输的效率和性能。