Skip to content

http2

HTTP2简介

基本特性

单个持久连接

所有 HTTP/2 连接都是永久的,而且仅需要每个来源一个连接。

​在HTTP/1.1协议中,如果客户端要想发起多个并行请求以提升性能,则必须使用多个TCP连接。这是 HTTP/1.x 交付模型的直接结果,该模型可以保证每个连接每次只交付一个响应(响应排队)。并且浏览器客户端在同一时间,针对同一域名下的请求有一定数量限制,超过限制数目的请求会被阻塞。更糟糕的是,这种模型也会导致队首阻塞,从而造成底层 TCP 连接的效率低下。

​该图总结了不同浏览器对该限制的数目。 浏览器对统一域名下请求的数量限制 ​目前站点通过配置多个静态资源域名来解决浏览器针对同一域名的请求数量限制。 ​ ​HTTP/2使用新的分帧机制,不再依赖多个TCP连接去并行复用数据流。因此,每个HTTP/2连接都是永久的,而且每个来源仅需要一个连接。服务器端可以设置连接交互超时时间,超时后关闭连接。 ​

多路复用

​​

允许同时通过单一的HTTP/2连接发起多重的请求-响应消息。

HTTP/2中新的二进制分帧层实现了完整的请求和响应复用:客户端和服务器可以将HTTP消息分解为互不依赖的帧,然后交错发送,最后再在另一端把它们重新组装起来。 http2多路复用

二进制分帧

在应用层和传输层之间增加一个二进制分帧层。

​在二进制分帧层中,HTTP/2会将所有传输的信息分割为更小的消息和帧(frame),并对它们采用二进制格式的编码,其中 HTTP1.x 的首部信息会被封装到 HEADER frame,而相应的 Request Body 则封装到 DATA frame 里面。 http2二进制分帧层 新的二进制分帧机制改变了客户端与服务器之间交换数据的方式。为了说明这个过程,我们需要了解 HTTP/2 的三个概念:

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

这些概念的关系总结如下:

  • 所有通信都在一个 TCP 连接上完成,此连接可以承载任意数量的双向数据流。
  • 每个数据流都有一个唯一的标识符和可选的优先级信息,用于承载双向消息。
  • 每条消息都是一条逻辑 HTTP 消息(例如请求或响应),包含一个或多个帧。
  • 帧是最小的通信单位,承载着特定类型的数据,例如 HTTP 标头、消息负载,等等。 来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装。

流消息帧

首部压缩 (HPACK压缩算法)

​每个 HTTP 传输都承载一组标头,这些标头说明了传输的资源及其属性。在 HTTP/1.x 中,此元数据始终以纯文本形式,通常会给每个传输增加 500–800 字节的开销。如果使用 HTTP Cookie,增加的开销有时会达到上千字节。为了减少此开销和提升性能,HTTP/2 使用 HPACK 压缩格式压缩请求和响应标头元数据,这种格式采用两种简单但是强大的技术:

  1. 这种格式支持通过静态 Huffman 代码对传输的标头字段进行编码,从而减小了各个传输的大小
  2. 客户端和服务器同时维护和更新一个包含之前见过的标头字段的索引列表,(换句话说,它可以建立一个共享的压缩上下文),此列表随后会用作参考,对之前传输的值进行有效编码。

​利用 Huffman 编码,可以在传输时对各个值进行压缩,而利用之前传输值的索引列表,我们可以通过传输索引值的方式对重复值进行编码,索引值可用于有效查询和重构完整的标头键值对。 头部压缩

作为一种进一步优化方式,HPACK 压缩上下文包含一个静态表和一个动态表:静态表在规范中定义,并提供了一个包含所有连接都可能使用的常用 HTTP 标头字段(例如,有效标头名称)的列表;动态表最初为空,将根据在特定连接内交换的值进行更新。因此,为之前未见过的值采用静态 Huffman 编码,并替换每一侧静态表或动态表中已存在值的索引,可以减小每个请求的大小。

数据流优先级

将 HTTP 消息分解为很多独立的帧之后,我们就可以复用多个数据流中的帧,客户端和服务器交错发送和传输这些帧的顺序就成为关键的性能决定因素。为了做到这一点,HTTP/2 标准允许每个数据流都有一个关联的权重和依赖关系:

  • 可以向每个数据流分配一个介于 1 至 256 之间的整数。
  • 每个数据流与其他数据流之间可以存在显式依赖关系。

数据流依赖关系和权重的组合让客户端可以构建和传递“优先级树”,表明它倾向于如何接收响应。反过来,服务器可以使用此信息通过控制 CPU、内存和其他资源的分配设定数据流处理的优先级,在资源数据可用之后,带宽分配可以确保将高优先级响应以最优方式传输至客户端。

服务器推送

​服务器可以对一个客户端请求发送多个响应。除了对最初请求的响应外,服务器还可以向客户端推送额外资源,而无需客户端明确地请求。 http2服务器推送

nginx配置http2

  1. 启用SSL。SSL不是http2规范的要求,但是当前http2的浏览器实现只在服务器支持SSL时使用。
  2. 安装最新的SSL软件。nginx实现http2使用了TLS的ALPN扩展,openssl 1.0.2及后续版本支持ALPN。
  3. 打开nginx的http2支持。 nginx启用http2

http2请求抓包

客户端在建立 TLS 连接的 Client Hello 握手中,通过 ALPN 扩展列出了自己支持的各种应用层协议。 client hello中APLNAPLN

服务端支持 HTTP/2,在 Server Hello 中指定 ALPN 的结果为 h2。 server hello中APLNAPLN

参考资料