Internet 从未停止过前进的脚步。早在 2015 年 HTTP/2 标准化之前,QUIC 的相关工作就已经开始了,而在之后 QUIC 成为了 HTTP/3。在向 IETF 提交首个 QUIC 规范草案五年之后的现在,我们有了 RFC 9000“QUIC:基于 UDP 的多路复用安全传输”。
当然,演变之路并不是那么轻松。在撰写本文时,业内共发布了四个 RFC,用于描述核心 QUIC 传输层和加密层。而另外 11 个相关的规范(包括 HTTP/3 的最终定义)仍处于草案阶段。然而,许多客户端和服务端的HTTP/3实现已得到广泛使用。事实上,得益于 CDN 提供商和科技巨头们向来紧跟标准草案的步伐,20% 的网站现已支持 HTTP/3。我们也不例外。
如欲深入了解 HTTP 的发展历程以及我们对 HTTP/3 和 QUIC 的实现,请观看此视频:
去年,我们推出了QUIC 和 HTTP/3 的技术预览版,之后还开展了许多工作。以下是 NGINX 实现 QUIC 和 HTTP/3 的关键开发工作摘要:
-
我们实现了多个 HTTP/3 草案版本,从草案 23 到草案 29(目前应用最广泛的版本),当然还有已经发布的 HTTP/3 标准(草案 34)。
-
我们不断将 NGINX 主线分支中的所有变更合并到 nginx-quic 分支,以便所有新功能(和问题修复)都可以在QUIC开发分支中进行测试。
-
我们参与了 QUIC 互操作测试,以便持续测试我们的实现与多种客户端的互操作性,并与其他服务器实现进行了对比。
-
我们开发了一个 eBPF 程序以利用 NGINX 的多进程架构。NGINX 使用多工作进程模式,可充分利用CPU多核来扩展性能。为了获得最大效率,针对每一个连接,我们倾向于使用同一工作进程来进行处理。然而 QUIC 使得这种处理方式变得棘手,因为连接不再与客户端的 IP 地址绑定,且 Linux 内核不提供 UDP 端口到进程的关联。为了解决这个问题,我们实现了一个 eBPF 扩展来集成
SO_REUSEPORT
,因此可以将 QUIC 连接 ID 映射到首先处理它的工作进程。这被巧妙地集成到 NGINX 内核中,以便 NGINX 将 eBPF 字节码加载到内核的套接字选择代码中。 -
我们整合了 NGINX 的连接处理代码,以简化长连接的配置方式。以前仅适用于 HTTP/1.1 的配置指令现在也同样适用于 HTTP/2,未来还将适用于 QUIC + HTTP/3。您不会再因协议版本不同而需要使用不同的指令来处理相同的功能了。请参阅
client_header_timeout
、keepalive_requests
、keepalive_timeout
及large_client_header_buffers
指令。 -
我们将新增的代码重构为两部分:较小的部分包含影响 NGINX 内核的更改,较大的部分包含传输协议的实现。通过以这种方式组织代码库,我们可以将对 NGINX 内核的变更保持在最低限度,从而降低将引入安全漏洞到NGINX的风险。
NGINX 路线图
我们的 QUIC + HTTP/3 路线图有两大里程碑:
- 将 nginx-quic 开发分支合并到 NGINX 主线分支
- 实现性能优化
QUIC 和 HTTP/3 协议的实现已基本完成,我们正在谨慎地将 nginx-quic 分支中的新代码合并到 NGINX 主线分支(即我们发布新功能的主线版本)。对 NGINX 内核的更改相对较小(约 3,000 行代码),合并正在顺利进行中。而工作量比较大的是合并传输协议代码(约 27,000 行代码)。根据以往将 HTTP/2 实现合并到 NGINX 的经验,这项工作预计将会耗时几个月。
我们当前的目标是,在 2021 年底将代码全部合并到 NGINX 主线分支,之后它将被后续版本的 NGINX 主线分支及 NGINX Plus 所包含。
在这之后,我们将专注于优化性能。QUIC 的有些优势是立竿见影的,但有些优势则需要时日才能显现。TCP 和 UDP 在操作系统内核和网络驱动程序层面的开发有着数十年的时间,因而具有一定优势,但 QUIC 主要是在操作系统用户空间中实现的 —— 这意味着一些我们认为理所当然的事情(例如拥塞通知和首选数据包大小检测),现在必须由每个客户端和服务器软件供应商自行实现。
集成 QUIC 的 TLS 层
QUIC 中加密传输成为了网络协议栈中强制性、不可协商的组成部分。QUIC 支持 TLS 1.3 标准,但 TLS 的软件实现也必须支持 QUIC 接口。NGINX 通常将 OpenSSL 用作外部依赖项,这意味着我们可以使用 官方 NGINX 开源版软件包和 NGINX Plus 中的操作系统自带的 SSL/TLS 库。通过将加密实现从 NGINX 中解耦,我们可以在不升级 NGINX 的情况下修复 SSL/TLS 库中的错误和安全漏洞。
在撰写本文时,OpenSSL 尚不支持 QUIC,而自带支持 QUIC 的 SSL/TLS 库的操作系统版本可能还需要好几个月的时间才能被交付。我们的 QUIC 实现目前支持 BoringSSL 和 OpenSSL 的 quictls 分支,不过它们必须使用 NGINX 进行编译。
我们预计,在我们将 nginx-quic 开发分支合并到 NGINX 主线分支的过程中, SSL/TLS 库对于 QUIC 的支持情况也将变得更加清晰。
如何助我们一臂之力
您可以帮助我们测试我们的 QUIC + HTTP/3 实现。您发现的错误和边界情况越多,我们就能越快地完成合并过程,从而使 NGINX 正式支持 QUIC + HTTP/3。
- 如果您熟悉 QUIC 和/或 HTTP/3,请对您熟悉的部分进行代码评审。
- 如果您运行大规模Internet服务,请为一些用户或服务部署 nginx-quic,以进行 A/B 测试。
- 如果您管理 Web 网站和/或应用,请在您的自动化测试(而非当前版本)中试用 nginx-quic。
- 烦请您通过 NGINX 开发者邮件列表与我们分享您的发现。
如要试用 nginx-quic 实现,您只需用浏览器打开 https://quic.nginx.org/ ,即可查看 README 了解更多信息。如要在您自己的环境中进行快速概念验证,请使用该 Dockerfile 构建自己的 nginx-quic 镜像,然后按照前面提到的 README 中的配置说明进行配置。
[编者按 – 后面的 Dockerfile 已在 2021 年 12 月更新,以修改原始版本中的错误。]