HTTP/2 的改进

HTTP/2 相比 HTTP/1.1 的主要改进和优化

问题

HTTP/2 相比 HTTP/1.1 有哪些改进?

解答

HTTP/1.1 存在的问题

TCP 连接数限制

浏览器对同一域名最多只能同时创建 6~8 个 TCP 连接。为了突破限制,出现了域名分片技术(将资源放在不同子域名下),但这会带来额外的 DNS 查询、三次握手、慢启动等开销,占用更多 CPU 和内存,在移动端问题更明显。

线头阻塞(Head Of Line Blocking)

每个 TCP 连接同时只能处理一个请求-响应,浏览器按 FIFO 原则处理请求。如果前一个响应未返回,后续请求都会被阻塞。虽然出现了管线化(pipelining)技术,但存在诸多问题:第一个响应慢仍会阻塞后续响应、服务器需要缓存多个响应、中途断连需要重新处理多个请求,且需要客户端-代理-服务器都支持。

Header 冗余

每次请求的 Header 内容多且变化不大,没有压缩传输优化方案。

优化手段的副作用

为了减少请求数,需要合并文件、雪碧图、资源内联等优化,但这导致单个请求内容变大、延迟变高,且内嵌资源无法有效使用缓存。

明文传输

HTTP/1.1 明文传输存在安全隐患。

HTTP/2 的改进

二进制分帧层(Binary Framing Layer)

帧是数据传输的最小单位,使用二进制传输代替明文传输,原本的报文消息被划分为更小的数据帧。

多路复用(Multiplexing)

在一个 TCP 连接上可以不断发送帧,每帧通过 stream identifier 标识所属的流。接收方根据 stream identifier 拼接每个流的所有帧。

将 HTTP/1.1 的每个请求当作一个流,多个请求变成多个流,请求响应数据分成多个帧,不同流中的帧交错发送,实现了单连接上多请求-响应并行。这解决了线头阻塞问题,减少了 TCP 连接数量和慢启动造成的问题。HTTP/2 对同一域名只需创建一个连接。

服务端推送(Server Push)

服务器可以主动向浏览器推送与请求相关的资源,浏览器无需发起后续请求。相比 HTTP/1.1 资源内联的优势:

  • 客户端可以缓存推送的资源
  • 客户端可以拒收推送的资源
  • 推送资源可以由不同页面共享
  • 服务器可以按优先级推送资源

Header 压缩(HPACK)

使用 HPACK 算法压缩首部内容,减少传输数据量。

应用层重置连接

HTTP/1.1 通过设置 TCP segment 的 reset flag 来关闭连接,会直接断开连接。HTTP/2 引入 RST_STREAM 类型的帧,可以在不断开连接的前提下取消某个请求的流。

请求优先级

每个流都可以设置依赖(Dependency)和权重,按依赖树分配优先级,解决关键请求被阻塞的问题。

流量控制

每个流都有自己的流量窗口,可以限制对端发送数据。两端都必须告知对方剩余空间,在窗口扩大前,对端只能发送限定大小的数据。

HTTP/1.1 优化手段可以弃用

合并文件、内联资源、雪碧图、域名分片对 HTTP/2 来说不再必要。使用 HTTP/2 应尽可能将资源细粒化,文件分解得更散,不用担心请求数过多。

关键点

  • 二进制分帧和多路复用实现单连接并行传输,解决线头阻塞和连接数限制
  • 服务端推送允许主动推送资源,客户端可缓存、拒收或共享
  • HPACK 算法压缩 Header,流量控制和优先级设置优化传输效率
  • 应用层重置连接避免断开 TCP 连接的开销
  • 资源细粒化成为最佳实践,无需合并文件和域名分片