Skip to content

HTTP3协议

HTTPS:// URL

HTTP/3将使用HTTPS:// URL履行。我们的世界里充斥着HTTPS URL,并且为新协议引入另一种URL方案被认为不切实际且完全不合理。如同HTTP/2一样,HTTP/3不会引入新的URL方案。

HTTP/2是传输HTTP的一种新方式,但是它还是基于TLS和TCP,这和HTTP/1一样。而在基于QUIC的HTTP/3中,情况更加复杂,它在一些重要的地方做了一些改变。

历史遗留下来的明文HTTP:// URL的处理方式将保持原样,随着我们迈入安全传输更加普及的未来,它的使用可能会越来越少。对HTTP URL的请求不会升级为使用HTTP/3。在实践中,因为其他一些理由,它们也很少升级到HTTP/2。

初始连接

当尝试连接到一个全新的、未访问过的网站时,到HTTPS:// URL的连接可能必须通过TCP(也许会有并行的一个QUIC连接)。因为主机可能是一个不支持QUIC的传统服务器,或者链路之间可能有阻碍QUIC成功连接的中间设备。

现代的浏览器和服务器可能在首次握手时协商HTTP/2协议。在连接建立并且服务器响应客户端的HTTP请求时,服务器可以通告客户端它对HTTP/3的支持与偏好。

使用Alt-svc自举

替代服务(alternative service, Alt-svc:)头部和它相对应的 ALT-SVC HTTP/2帧并不是特别为QUIC和HTTP/3设计的。它是为了让服务器可以告诉客户端 “看,我在这个主机的这个端口用这个协议提供相同的服务” 而设计的。详见RFC 7838

如果初始连接使用的是HTTP/2(甚至HTTP/1),服务器可以响应并告诉客户端它可以再试试HTTP/3。连接可以指向相同主机或者不同但提供相同服务的主机。Alt-svc回复中有一个到期计时器,让客户端可以在指定的时间内使用建议的替代协议将后续的连接和请求直接发送给替代主机。

例子

一个HTTP服务器的响应中包含了如下的一个 Alt-Svc: 头部:

Alt-Svc: h3=":50781"

这指示了同一名称的主机在UDP端口50781提供HTTP/3服务。

然后,客户端可以尝试与该端口建立QUIC连接。如果成功,后续将通过该连接继续通信,代替初始的HTTP版本。

QUIC流与HTTP/3

HTTP/3针对QUIC设计,所以它可以利用QUIC流的所有好处。而HTTP/2不得不在TCP之上构建它的数据流和复用概念。

通过HTTP/3传输的HTTP请求使用一系列的数据流完成。

HTTP/3帧(frame)

HTTP/3意味着建立QUIC数据流,并将一系列帧发送给对方。HTTP/3中的数据帧种类不多且固定(截至2018年12月18日有九种)。最关键的帧可能是:

  • HEADERS:发送压缩的HTTP头部

  • DATA:发送二进制数据内容

  • GOAWAY:请关闭此连接

HTTP请求

客户端通过其发起的 双向 QUIC流来发送HTTP请求。

一个请求包括一个HEADERS帧,之后可能有一两种其他的帧:一系列的DATA帧,以及可能有一个作为末尾的HEADERS帧。

发送一个请求后,客户端会关闭该数据流以进行发出。

HTTP响应

服务器在双向流上发回其HTTP响应。其中含有一个HEADERS帧,一系列DATA帧,末尾可能有一个HEADERS帧。

QPACK头部

HEADERS含有用QPACK算法压缩的HTTP头部。QPACK与HTTP/2中的HPACK(RFC 7541)类似,并针对乱序流做了相应修改。

QPACK本身在两个端点间使用两个额外的单向QUIC流,用于在两个方向上传递动态表信息。

优先度

HTTP/3中有一种帧是优先度(PRIORITY)。与HTTP/2中的类似,它用于设定一个流的优先度和依赖关系。

该帧可以设定一个流依赖于另一个流,也可以设定特定流的“权重”。

服务器应该只在一个流所依赖的所有流都被关闭,或者都无法取得进展时为该流分配资源。

一个流的权重是介于1到256之间的值,有着相同父系流的流应该按照权重的比例分配资源。

服务器推送

HTTP/3的服务器推送与HTTP/2(RFC 7540)类似,但机制上有所不同。

服务器推送实际上就是对一个未曾发出的客户端请求做出响应!

服务器推送仅在客户端同意的前提下才允许发出。在HTTP/3中,客户端甚至能通过通告给服务器的最大推送流ID来设置所接受推送的次数限制。超出限制将导致连接错误。

如果服务器端认为客户端可能需要某个并未要求但应该有的额外资源,服务器可以通过请求流发送一个 PUSH_PROMISE 帧,使该推送请求看上去像是一个响应,然后通过新的流发送实际响应。

虽然客户端之前已经表示过推送可接受,但如果客户端认为适合,每个推送流仍可以随时取消,然后发送一个 CANCEL_PUSH 帧到服务器。

问题重重

自从推送这一特性在HTTP/2中讨论、开发、部署以来,它就备受争议、讨论和抨击。为了让它有用,人们付出了许多努力。

推送从来不是没有代价的,尽管它省了半个往返的延迟,它还是会消耗带宽。服务器也很难或不可能从高层面确定一个资源是否应该被推送过去。

与HTTP/2的比较

HTTP/3面向QUIC设计,QUIC是一个自己处理数据流的传输层协议。

HTTP/2面向TCP设计,因此数据流在HTTP层处理。

相似之处

这两个协议为客户端提供了几乎相同的功能集。

  • 两者都提供数据流
  • 两者都提供服务器推送
  • 两者都有头部压缩,QPACK与HPACK的设计非常类似
  • 两者都通过单一连接上的数据流提供复用
  • 两者都提供数据流的优先度设置

不同之处

两个协议的主要不同点在于细节,不同之处主要由HTTP/3使用的QUIC带来。

  • 得益于QUIC的0-RTT握手,HTTP/3可以提供更好的早期数据支持,而TCP快速打开和TLS通常只能传输更少的数据,且经常存在问题。
  • 得益于QUIC,HTTP/3的握手速度比TCP+TLS快得多。
  • HTTP/3不存在明文的不安全版本。尽管在互联网上很少见,HTTP/2还是可以不配合HTTPS来实现和使用。
  • 通过ALPN拓展,HTTP/2可以直接在TLS握手时进行协商。HTTP/3基于QUIC,所以需要凭借响应中的 Alt-Svc: 头部来向客户端宣告。

前端知识体系 · wcrane