概述

HTTP/2 是由 Google 的 SPDY 演变而来,Chrome 在2016 年宣称结束对 SPDY 的支持,由此 SPDY 也完成他的历史使命。HTTP/2 协议出现并非为了颠覆 HTTP/1.x,它的目的是对现有的协议不做大的变更,用户感知不到底层协议变更(比如 HTTP 的状态码依旧保留并正常使用,URI 还是以 http:// 或 https:// 开头等等),但要使得页面性能提升 50% 以上,HTTP/2 可以说做到了这一要求。在很久的一段时间内,HTTP/1.x 和 HTTP/2 会一直共存,但由于 HTTP/2 协议兼容 HTTP/1.x,所以用户申请部署非常方便。
HTTP/2 既要提高性能,又要兼容 HTTP/1.x,那它是如何完成的呢? HTTP/2 把 HTTP 分解成语义和语法两个部分,语义层不做改动,比如请求方法、请求头语义保持不变,在语义上保持和 HTTP/1.x 兼容,但是语法,也就是传输形式被改得面目全非,具体表现在:

  • 首部压缩。
  • 二进制分帧。
  • 流量控制。
  • 更安全的 TLS。
  • 服务端推送。
  • 请求/响应多路复用。

下面,我会一一讲解。

细数 HTTP/1.1 的痛点

痛点一:网络利用率低

HTTP/1.1 网络利用率低具体表现在:

  • 浏览器只使用 4~8 个连接用来处理大量的资源请求。
  • 头部阻塞。
  • 同时,当你使用多个连接时,TCP表现得非常糟糕。

    痛点二:头部冗长

    HTTP/1.1 头部包含特别多的冗余信息:

  • 超过 1000+ 字节请求头是非常常见的,比如 Cookie、Referer等。

  • 这些请求头的数据多数是重复的。
  • 由于 TCP 的慢启动,这些大量的携带大的请求头在连接的开始是缓慢的。

    优化 HTTP/1.1

  • 网络分发对 HTTP/1.1 是有害的。因为增加了拥塞事件的发生概率,而且头部压缩更差。如果 DNS 和 Cert 同意的话,可以使用连接聚合。

  • HTTP/1.1 用于减少 HTTP 请求数量的优化操作可能会降低 HTTP/2 的性能。比如雪碧图、代码内嵌和串联(concatenation)。
  • 在 HTTP/1.1 中,是通过浏览器决定请求的优先级和顺序。在 HTTP/2,这取决于服务端。
  • 服务端推送可以节约一个消息往返时间: 在浏览器知道要使用某些数据之前,服务端主动推送这部分数据。

    二进制分帧层

    前面说过,HTTP/2 并没有重写 HTTP/1.x 语义,但语法(换做语言可能更容易理解些)彻底被重构,二进制分帧层的设计是重要的一环。
    HTTP2_二进制分帧层.png
    这里所谓的,指的是位于套接字接口与应用可见的高层 HTTP API 之间的一 个新机制:HTTP 的语义,包括各种动词、方法、首部都不受影响,不同的是传输期间对它们的编码方式变了。HTTP/1.x 以换行符作为纯文本的分隔符,而 HTTP/2 将所有传输的信息分割为更小的消息,并对它们采用二进制格式的编码。
    在应用层和会话层或传输层之间多了一个二进制分帧层,是它帮助我们完成 HTTP/2 的语法的解码和编码操作,这部分对应用层来说是透明的。

    流(Stream)、消息(message)和帧(frame)

    新的二进制分帧层的出现,带来的几个陌生的概念,分别是流、消息和帧,对它们有如下解释:
概述 描述
在已建立的连接中字节可双向流动,字节流可携带一个或多个消息
消息 一个完整的帧序列,可以映射到一个逻辑请求或响应
HTTP/2 通信的最小单位,每个帧包含帧首部,最低要求要包含当前帧所属的流

所有 HTTP/2 通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流。相应地,每个数据流以消息的形式发送,而消息由一或多个帧组成,这些帧可以乱序发送,然后再根据每个帧首部的流标识符重新组装。
知识点总结如下:

  • 所有通信都在一个 TCP 连接上完成。收益与风险并存。
  • 流是连接中的一个虚拟通道,具有双向性。每个流都有一个唯一的整数标识符。
  • 消息是指逻辑上的 HTTP 消息,比如对 HTTP/1.1 请求而言,包含请求行、请求头和请求体。他们在 HTTP/2 中由一个或多个帧组成。
  • 帧是 HTTP/2 的最小通信单位,并有不同的帧类型。HTTP/2 中新的二进制分帧层突破了这些限制,实现了多向请求和响应:客户端和服务器可以把 HTTP 消息分解为互不依赖的帧,然后乱序发送,最后再在另一端把它们重新组合起来。

HTTP2_流消息和帧.png
简而言之,HTTP/2 将 HTTP 协议的通信分解为二进制分帧的交换,这些帧属于某个流中的某个消息,由多个帧组成一个完整的消息。并且,多个流在一条 TCP 连接上传输,这是 HTTP/2 协议提供的功能和性能优化的基础。

请求/响应多路复用(Multiplexing)

在理解多路复用之前,有几个点需要大家清楚:

  1. 浏览器依据域名和服务器建立 TCP 连接,一般 PC 端对单个域名同时建立 6~8 条 TCP 连接,手机端则为 4~6 条。每一个请求和响应都占用一个 TCP 连接。在任一时刻,任一一条 TCP 连接上同时只能存在一个请求/响应。容易造成队头阻塞。
  2. 如今绝大部分的门户网站首页大小都会超过 2M,请求数量可以多达 100 个。
  3. TCP 成功建立连接后,需要经历慢启动过程。

对于 HTTP/1.1 ,它是通过以下手段优化用户体验,降低延迟:

  • Keep-Alive。HTTP/1.1 默认 TCP 为长连接,后续请求可以复用 TCP 连接,减少 TCP 慢启动带来的延迟。
  • 管道(Pipelining) 。本质是合并请求,提高服务端资源复用率。但容易造成队着阻塞,增加服务端内存开销。管道并没有普及。
  • WebSocket。在 HTTP 协议的基础上升级为 WebSocket,提供双向的数据通道。提供 Message 的概念,相对 HTTP 报文来说携带的信息更少,传输效率更高。
  • 并发请求。浏览器针对特定的域名只能建立 6~8 条 TCP 连接,这是远远不够的。那怎么办呢? 通过域名散列(domain sharding) 的方式变相提高 TCP 连接数。带来的影响是增大网络拥塞的概率,且 TCP 利用率低下。
  • 合并请求。包含图片合并生成雪碧图、连接文件等。代码、文件耦合严重,更新修改困难。

HTTP/2 中新的二进制分帧层消除了1、2、3 点的限制,它允许客户端和服务端将 HTTP 请求/响应的消息拆分成独立的帧,待发送时可以不按顺序发送,然后在另一端重新组装它们,从而实现完整的请求和响应。
HTTP2在共享的连接上同时发送请求.png
把 HTTP 消息拆分成多个独立的帧,记录这些帧元数据信息也会是一笔不小的开销,应该简洁如同 TCP 协议那样高效。好在 HTTP/2 的帧的元数据要求不多,完整的 HTTP/2 帧详解等会在下面详解。如果对 WebSocket 协议比较熟的话,协议定义的思路是相似的。
从上图可以看出,在某一时刻的某一条 TCP 通道中,同时出现三个请求/响应消息进行交换,客户端接收帧后组装并还原成逻辑消息,随后返回给应用程序。请求/响应多路复用带来的好处总结如下:

  • 可以并行交错地发送请求,请求之间互不影响。
  • 可以并行交错地发送响应,响应之间互不干扰。
  • 只使用一个连接即可并行发送多个请求和响应。
  • 消除不必要的延迟,从而减少页面加载的时间。
  • 不必再为绕过 HTTP/1.x 限制而多做很多工作。

由于 HTTP/2 底层还是基于 TCP 协议,所以并没有彻底解决队首阻塞问题,但相比 HTTP/1.1 而言性能也得到极大提升。

流的优先级

HTTP/2 将消息分割成多个单独的帧,并且允许多个流共用同一条 TCP 连接。那么,这些帧在客户端和服务端传递的顺序就成为一个关键的性能考虑因素。比如某些请求需要立即被响应,有些优先级不高,可以延后。为了方便这一点,HTTP/2 标准允许每个流具有权重依赖关系

  • 可以为每个流分配一个 1~246 之间的整数,称为权重。
  • 一个流可以对另一个流有一个明确的依赖关系。他的 Stream ID 等于被依赖的 Stream ID。

权重和依赖关系的组合可以构建成一棵优先级数:
HTTP_2_优先级树.png
服务端通过树的信息对不同流分配不同的 CPU、内存等资源。确保以最优化的方式响应客户端的不同优先级的请求。分配策略简述如下:

  • 父流总是优于子流进行响应。
  • 父流相同的情况下,子流根据权重分配相应资源。

有了优先级,服务端在处理不同的流时可以采取不同的策略:以最快的方式处理优先级高的帧,降低延迟,从而提升用户体验。

浏览器在渲染页面时,并非所有的资源都可以同时加载,他们之间可能会存在先后关系。所有现代浏览器都会基于资源的类型以及它在页面中的位置排定请求的优先次序,甚至通过之前的访问来学习优先级模式。

每域名每连接

随着新的二进制分帧层的提出,HTTP/2 不再需要多个 TCP 连接并行处理多个请求/响应。而是每个请求/响应被分割成多个帧,这些帧可以交替传送或根据优先级传送。因此,所有的 HTTP/2 连接都是持久的,每个源(origin)只需要一个连接。
多数 HTTP 传输是短暂的且突发的,但 TCP 是针对长期(long-lived)、大容量数据传输进行优化。HTTP/2 通过重用相同连接能够有效地使用每条 TCP 连接,并且能显著降低整体的 TCP 连接开销。在 HTTP/1.1 时代可能需要维持 100 个 TCP 连接,但有了 HTTP/2,每个源只会有一条 TCP 连接,所以现在只需要维护 10 条 TCP 连接(近似值)就能达到不错的性能。除了能降低系统资源的消耗,也能降低 TCP 的拥塞概率,并提高了网络利用率和容量。

流量控制

在同一个 TCP 连接上传输多个数据帧,这意味着要共享带宽。只有优先级还不足以确保资源正确有效分配。HTTP/2 为数据流和连接的流量控制提供了一个简单的机制:

  • 流量控制具有方向性(directional)。每个接收者可以选择为每个流和整个连接设置所需的任何窗口大小。
  • 流量控制是基于信用的。每个接收者都通告其初始连接和流量控制窗口初始值(单位:字节),每当发送方发出 DATA 帧时,该窗口就会减小。通过 WINDOW_UPDATE 帧增大流量控制窗口。
  • 无法禁用流量控制。客户端和服务端在建立 HTTP/2 连接时交换 SETTINGS 帧,在各自方向上控制窗口大小。流量控制窗口默认值为 65535 字节,但接收方可以设置一个更大的值(最大值为 网络协议之HTTP/2 - 图6)。无论何时,任意数据被接收到都可以发送 WINDOW_UPDATE 帧来维护窗口值。
  • 流量控制是逐跳的(hop-by-hop)并非端到端。也就是说,帧所流经任何一个中间节点都可以根据自身标准和具有启发式方式来实现资源的分配机制。

    HTTP/2 连接建立后,客户端与服务端交换 SETTINGS 帧,目的是设置双向的流量控制窗口大小。其实,HTTP/2 的流量控制思路是和 TCP 的流量控制思路是想通的,但是 TCP 不能对连接内的流进行差异化流量控制,它针对的是整体环境。因此,HTTP/2 的流量控制是针对单条 TCP 连接内部的流而言。 HTTP/2 标准并没有规定任何特定的算法、值,因此,实现者可以选择自己的算法以匹配自己的应用场景,从而求得最佳性能。

服务端推送

服务端推送是 HTTP/2 强大的功能之一。Server Push 可以使得服务端能够为单个客户端发送多个响应。也就是说,除了对客户端原始请求响应外,还可以主动将其他资源推送到客户端,而客户端不必显示请求每个资源。
HTTP2_服务器推送.png
为什么我们需要这种机制呢? 一个典型的 Web 应用程序是由几十个资源组成的,所有资源都需要客户端通过检查服务端响应的文档来发现。那为什么不消除额外的延迟让服务端主动推送相关的资源到客户端呢?因为服务端已经知道客户端所需要的所有资源文件列表。
其实,针对 HTTP/1.x 的某些优化手段(比如内联 CSS、JavaScript 或其它某些内容)可以看成是使用服务端主动推送的实现方式之一。只不过现在 HTTP/2 提供一种更可靠的、更方便的途径,这个就是 Server Push。对服务端推送的资源,所推送的资源有以下准则:

  • 推送的资源可以被客户端缓存下来。
  • 推送的资源可以在不同页面上被重用。
  • 推送的资源可以与其他资源一起进行多路复用。
  • 推送的资源可以由服务端进行优先级排序。
  • 推送的资源可以被客户端拒绝。

每个推送的资源都是一个流,允许客户端单独地对其进行加工、优化化和处理。唯一的安全限制是所推送的资源必须遵守同源策略(same-origin policy)。
所有的服务器推送流都是通过 PUSH_PROMISE 帧启动的,这表明服务端将要所描述的资源推送到客户端,并且需要在推送资源响应数据之前进行传递。这个传递顺序十分重要:因为客户端需要知道服务端打算推送哪些资源,从而避免对这些资源创建重复的请求。满足此要求最简策略是在父级响应(如 DATA 帧)之前发送所有 PUSH_PROMISE 帧,这些帧仅包含服务端承诺发送的资源头部信息。
一旦客户端收到 PUSH_PROMISE 帧,它可以通过 RST_STREAM 拒绝接收。而 http/1.1 则是强制接收,这是一个重要的改进。

首部压缩 HeaderCompression

HTTP 的每一次传输都会携带一组用于描述所传输的资源及其属性的首部。在 HTTP/1.1 中这部分元数据是以纯文本形式发送,大约每次传输都会增加 500~800 字节的开销,如果 HTTP cookie 头部被使用,则可能会增加千字节(kilobytes)开销。为了减少这种开销并提高性能,HTTP/2 使用 HPACK 压缩请求和响应头的元数据信息。该格式使用了两种简单但功能强大的技术:

  1. 它允许传输的头字段通过静态哈夫曼编码。从而减少各自的传输大小。
  2. 它要求客户端和服务端维护和更新以前所交换过的头字段索引列表(即建立一个共享的压缩上下文),然后基于此,有效地编码以前传输的值。

HTTP/2 在客户端和服务器端使用首部表来跟踪和存储之前发送的键-值对, 对于相同的数据,不再通过每次请求和响应发送。

  • 首部表的生命周期和 HTTP/2 的连接一样,底层 TCP 连接断开,则首部表被清除。
  • 每个新的首部键-值对要么被追加到当前表的末尾,要么替换表中之前的值,客户端和服务器共同渐进地更新。

客户端和服务端各自维护首部表,它们都清楚地知道已经发送了哪些首部,值是什么,从而可以根据之前的数据只编码并发送差异数据,随着时间的增加,可能会出现 0 首部的情况。
HTTP2_首部的差异化编码.png
上面的图表示:请求#2 在发送之前需要和首部表对比,发现只有 :path 不一致,所以就只对 :path 数据进行编码即可,从而显著减少每个请求的开销。
全面 HTTP/2 压缩算法,请看这里
更一步优化,HPACK 压缩上下文是由静态表和动态表组成。

  • 静态字典(static table) 包含所有连接可能使用到的头字段列表。比如 method、referer 等。静态字典完整表格在这里
  • 动态字典 (dynamic table) 最开始为一张空表,随着在特定连接中帧的交换次数增加而被更新。

结果,通过静态哈夫曼编码来处理以前从未见过的值,并用索引代替每一侧的静态或动态表已经存在的值,从而减小了每个请求的大小。
hpack-header-compression.png.webp
最左边的 Reqeust headers 需要被传送到对端,内容是我们熟知的 HTTP 请求头信息,比如请求方法为 GET等等,中间是静态字典(static table)和动态字典(dynamic table),最右侧是已编码的首部信息。通过右则的编码信息我们可以看出,静态字典和动态字典相同的 key 都被编码为对应的索引值,而不存在的 key 和 value 都通过哈夫曼编码后要么追加到末尾,要么由于之前已经存在字典中则添加到对应位置。
使用字典可以极大地提升压缩效果,静态字典在首次请求就可以使用,对于静态、动态字典中不存在的内容使用哈夫曼编码减少传输的体积。客户端和服务端分别有相同的静态字典和动态字典,它们随着帧的发送会随时更新并保持一致。

实现细节

一个 Key 和 value 键值对会有以下几种情况:

  • key 和 value 都在字典中。
  • key 在字典,更新动态字典。
  • key 不在字典,更新动态字典。
  • key 在字典,不允许更新动态字典。
  • key 不在字典,不允许更新动态字典。

发现 HTTP/2

在未来的一段时间内,HTTP/1.1 和 HTTP/2 会共存。因此,大多数服务器和客户端在此期间必须同时支持 1.x 和 2.0 标准。于是,支持 HTTP/2 的客户端在发起新请求之前,必须能发现服务器及所有中间设备(比如路由器)是否支持 HTTP/2 协议,有三种可能的情况:

  • 通过 TLS 和 ALPN 发起新的 HTTPS 连接
  • 根据之前的信息发起新的 HTTP 连接
  • 没有之前的信息而发起新的 HTTP 连接

HTTPS 协商过程中有一个环节会使用 ALPN(Application Layer Protocol Negotiation) 发现和协商 HTTP/2 的支持情况。
若通过常规非加密(即 HTTP)建立 HTTP/2 连接则需要多做一点工作。因为端口共用,又没有服务器是否支持 HTTP/2 的其他任何信息,此时客户端只能使用 HTTP Upgrade 机制通过协调确定适当的协议:

  1. GET /page HTTP/1.1
  2. Host: server.example.com
  3. Connection: Upgrade, HTTP2-Settings
  4. Upgrade: HTTP/2.0
  5. HTTP2-Settings: (SETTINGS payload)
  6. HTTP/1.1 200 OK
  7. Content-length: 243
  8. Content-type: text/html
  9. (... HTTP 1.1 response ...)
  10. (or)
  11. HTTP/1.1 101 Switching Protocols
  12. Connection: Upgrade
  13. Upgrade: HTTP/2.0
  14. (... HTTP 2.0 response ...)
  • 如果服务器不支持 HTTP/2 ,则立即返回 HTTP/1.1 响应。否则,服务器就会以 HTTP/1.1 格式返回 101 Switching Protocols 响应。立即切换 HTTP/2 后使用新的二进制分帧协议返回响应。

    二进制分帧简介

    与 HTTP/1.1 使用的纯文本不同,基于二进制的分帧会使得通信简洁高效。帧是 HTTP/2 传输的最小单位,所有帧都共享一个 8 字节首部,分别定义帧的长度、类型、标志和流标识符。具体表示如下图所示:
    HTTP2_二进制分帧层.png
    1. +-----------------------------------------------+
    2. | Length (24) |
    3. +---------------+---------------+---------------+
    4. | Type (8) | Flags (8) |
    5. +-+-------------+---------------+-------------------------------+
    6. |R| Stream Identifier (31) |
    7. +=+=============================================================+
    8. | Frame Payload (0...) ...
    9. +---------------------------------------------------------------+
字段 位数 说明
长度 Length 24 单帧可携带数据量默认上限是 ,最大上限是 。
即通常不超过 16KB,最大不超过 16MB。
类型 Type 8 定义帧的格式和语义。大致可分为数据帧和控制帧。
数据帧:HEADERS、DATA。存放 HTTP 报文。
控制帧:SETTINGS、PING、PRIORITY。用来管理流的控制帧。
标志 Flags 8 携带简单的控制信息。
比如:END_HEADERS 表示头数据结束、
END_STREAM 表示单方向数据发送结束(EOS,End Of Stream)
R 1 保留位,始终为 0
流标识符
Stream Identifier
31 唯一标识 HTTP/2 的流

HTTP/2 定义了如下帧类型 网络协议之HTTP/2 - 图11

之所以要递增一个大版本到 2.0,主要是因为它改变了客户端与服务器之间交换数据 的方式。为实现宏伟的性能改进目标,HTTP 2.0 增加了新的二进制分帧数据层,而 这一层并不兼容之前的 HTTP 1.x 服务器及客户端——是谓 2.0。

典型的HTTP工作模式是点对点的,其中包括2个参与者,即客户端和服务器,尽管还可以引入其它参与者,如正向代理,反向代理,但其本质上还是点到点的。其它角色或扮演客户端,或服务器,或二者,充当中间人参与到HTTP的通讯中,HTTP协议本身仅通过特定头字段标记【Via】是否通过中间人转发,并不改变点到点通讯的本质。
进一步,在HTTP/1.1中客户端发送请求,服务器回应客户端的请求,客户端发送的每一个请求,需要等待服务器回应后才能发送下一个请求,即所有请求在一个FIFO队列里,如果队头请求意外阻塞,这样就会造成队头阻塞。即如果队头的请求响应时间太长,会影响后面的请求的处理。类比现实中,去银行办理业务,队列前面有个行动迟缓的老太太,崩不崩溃?
在HTTP/1.1中有3个方法可以缓解,但不能解决队头阻塞问题。

管道,即可以并发多个请求,无需等待上一个请求返回,即现在的FIFO的长度可以>1。但它仍然期待按发送次序收到响应消息,如果某个先发请求阻塞,则后继报文即使处理也不能发出,所以仍然存在队头阻塞问题。管道仅在理想情况下,提高收发效率。而且目前浏览器,服务器对管道支持得不好,可以认为是废弃技术。
并发TCP连接,对于同一个域名,浏览器允许同时开6-8个TCP连接,因为每个TCP连接独立,所以某个TCP中的HTTP请求阻塞,不影响其它TCP连接,所以虽然队头阻塞仍然存在,但因为存在多个独立的TCP连接,所以队头阻塞问题得到一定程度的缓解。
域名分片Domain Sharding,即多个域名映射到一个IP,即可以并发6域名的连接,进一步缓解了队头阻塞的负面影响。
HTTP/2解决了用流和分帧的方式HTTP的队头阻塞问题。
HTTP/3解决了用UDP+QUIC解决了TCP队头阻塞的问题。
HTTPS 采用的是对称加密*非对称加密
结合的「混合加密」方式:

  • 在通信建立前采用非对称加密的方式交换「会话秘钥」,后续就不再使用非对称加密。
  • 在通信过程中全部使用对称加密的「会话秘钥」的方式加密明文数据。

采用「混合加密」的方式的原因:

  • 对称加密只使用一个密钥,运算速度快,密钥必须保密,无法做到安全的密钥交换。
  • 非对称加密使用两个密钥:公钥和私钥,公钥可以任意分发而私钥保密,解决了密钥交换问题但速度慢。

    HTTP/2 协议由以下两个 RFC 组成:

  • Hypertext Transfer Protocol version 2 - RFC7540

  • HPACK - Header Compression for HTTP/2 - RFC7541

HTTP/2 缺点

  1. Packet Loss, High-RTT Links, and HTTP/2 Performance 包丢失、高 rtt 链路和 HTTP/2性能
  2. Wait, I hear you say, we listed the benefits of using one TCP connection per origin but arent there some potential downsides? Yes, there are.
  3. 等等,我听到你说,我们列出了每个源使用一个 TCP 连接的好处,但是没有一些潜在的缺点吗?是的,有。
  4. We have eliminated head-of-line blocking from HTTP, but there is still head-of-line blocking at the TCP level (see Head-of-Line Blocking).
  5. 我们已经从 HTTP 中消除了队头阻塞,但是在 TCP 层面仍然存在队头阻塞/队头阻塞。
  6. Effects of bandwidth-delay product may limit connection throughput if TCP window scaling is disabled.
  7. 如果禁用 TCP 窗口扩展,频宽延迟乘积的影响可能会限制连接吞吐量。
  8. When packet loss occurs, the TCP congestion window size is reduced (see Congestion Avoidance), which reduces the maximum throughput of the entire connection.
  9. 当数据包丢失发生时,TCP 拥塞窗口大小减小(参见避免拥塞) ,从而降低了整个连接的最大吞吐量。
  10. Each of the items in this list may adversely affect both the throughput and latency performance of an HTTP/2 connection. However, despite these limitations, the move to multiple connections would result in its own performance tradeoffs:
  11. 此列表中的每个项都可能对 HTTP/2连接的吞吐量和延迟性能产生负面影响。然而,尽管有这些限制,转移到多个连接将导致其自身的性能折衷:
  12. Less effective header compression due to distinct compression contexts
  13. 由于不同的压缩上下文,有效的报头压缩较少
  14. Less effective request prioritization due to distinct TCP streams
  15. 由于不同的 TCP 流,请求优先级排序效率较低
  16. Less effective utilization of each TCP stream and higher likelihood of congestion due to more competing flows
  17. 每个 TCP 流的有效利用率较低,由于更多的竞争流导致拥塞的可能性较高
  18. Increased resource overhead due to more TCP flows
  19. 由于更多的 TCP 流而增加了资源开销
  20. The above pros and cons are not an exhaustive list, and it is always possible to construct specific scenarios where either one or more connections may prove to be beneficial. However, the experimental evidence of deploying HTTP/2 in the wild showed that a single connection is the preferred deployment strategy:
  21. 以上的优点和缺点并不是一个详尽的列表,而且总是可以构建特定的场景,其中一个或多个连接可能被证明是有益的。然而,在通用环境中部署 HTTP/2的实验证据表明,单一连接是首选的部署策略:
  22. In tests so far, the negative effects of head-of-line blocking (especially in the presence of packet loss) is outweighed by the benefits of compression and prioritization.
  23. 到目前为止,在测试中,压缩和优先级排序的好处大于队头阻塞的负面影响(特别是在存在丢包的情况下)。
  24. Hypertext Transfer Protocol version 2, Draft 2
  25. 超文本传输协议版本2,草案2
  26. As with all performance optimization processes, the moment you remove one performance bottleneck, you unlock the next one. In the case of HTTP/2, TCP may be it. Which is why, once again, a well-tuned TCP stack on the server is such a critical optimization criteria for HTTP/2.
  27. 与所有性能优化过程一样,一旦消除了一个性能瓶颈,就可以解锁下一个瓶颈。在 HTTP/2的情况下,TCP 可能就是。这就是为什么服务器上经过良好调优的 TCP 堆栈是 HTTP/2的关键优化标准的原因。
  28. There is ongoing research to address these concerns and to improve TCP performance in general: TCP Fast Open, Proportional Rate Reduction, increased initial congestion window, and more. Having said that, it is important to acknowledge that HTTP/2, like its predecessors, does not mandate the use of TCP. Other transports, such as UDP, are not outside the realm of possibility as we look into the future.
  29. 目前正在进行的研究,以解决这些问题,并提高 TCP 性能的一般: TCP 快速开放,比例速率降低,增加初始拥塞窗口,等等。话虽如此,重要的是要承认,HTTP/2和它的前辈一样,并没有强制要求使用 TCP。当我们展望未来的时候,其他的传输协议,比如 UDP,并不是不可能的。

参考

RFC 7540
High Performance Browser Networking#Chanper12
HTTP/2 相比 1.0 有哪些重大改进?
极客时间-透视 HTTP 协议

我的公众号公众号封面.png