NGINX QUIC & HTTP/3 最新进展
原文作者:汤炜涛
转载来源:NGINX 开源社区
NGINX 唯一中文官方社区 ,尽在 http://nginx.org.cn/
Internet 从未停止过前进的脚步。早在 2015 年 HTTP/2 标准化之前,QUIC 的相关工作就已经开始了,而在之后 QUIC 成为了 HTTP/3,当然,演变之路并不是那么轻松。如今 QUIC 和 HTTP/3 协议发展到何种程度?本次分享汤炜涛老师回顾 HTTP 协议的发展历程。
介绍 QUIC 和 HTTP/3 协议,HTTP/3 协议的优点以及为什么需要 HTTP/3 协议。介绍 NGINX 对 QUIC 和 HTTP/3 协议的支持,讲解版本要求和配置方法。
HTTP 协议的发展
首先简短回顾一下 HTTP 协议发展历程。HTTP 协议最早诞生在欧洲核子中心,目前我们把在 HTTP/1.0 正式发布之前的所有协议统称为 HTTP/0.9,最初的 HTTP/0.9 是一个非常简单的协议,仅有 GET 一种方法,直到 HTTP/1.0 才发展成了大家现在所熟悉的 HTTP 协议,现在为止 HTTP/1.0 依然在广泛的使用。
HTTP/1.1 以 HTTP/1.0 为基础进行了一些优化,是目前为止互联网使用最多的协议。它最大的优化在于引入了会话机制,当我们的客户端和服务器之间连续请求多个资源时,并不会像 HTTP/1.0 一样,每请求一个资源就建立一个 TCP 连接,而是保留一个 TCP 会话连接,后续的资源都可以用已有的 TCP 连接来去进行传输,增加了 TCP 连接的使用效率。
但是如果想一次性并发请求多个资源,在 HTTP/1.1 协议下,为了提高效率通常会一次性并发建立多个 TCP 连接,这会在效率上有所浪费。所以 HTTP/2 最大的变化是加入了连接复用机制,即当客户端要并发请求多个资源时,可以在一个 TCP 连接里完成,引入了 Stream 流机制去解决并发传输的问题。另外,HTTP/2 把 TLS 加密变成了强制性。
HTTP/3 最大的改进就是把 HTTP 协议一直在使用的传输层协议,从 TCP 改到了基于 UDP 的 QUIC 协议。
目前 HTTP/1 依然是主流协议,对于 HTTP/2 来说,已有超过 40% 的网站支持,仅有不足 26% 的网站支持 HTTP/3。
HTTP/2 存在队头阻塞这一个大问题。这个原因前面有说过,HTTP/2 协议引入了连接复用机制,可以使我们在一个 TCP 通道里并行请求多个资源,而不像传统的 HTTP/1 协议存在顺序性,并且 HTTP/2 把 HTTP/1 的文本格式传输优化为二进制传输,但这样的改进也带来新的问题——队头堵塞。
TCP 是一个可靠的传速层协议,它需要接收端回复信息之后才会进行后续的数据传输,但是这样就会导致资源传输慢,甚至效率还不如 HTTP/1,因为 HTTP/1 还可以并发多个 TCP 连接请求多个资源。但是对于 HTTP/2 来说,当所有的资源都放在同一个连接里面顺序传输时,某一个环节出错后,后续的环节也不会进行下去,造成队头堵塞问题。
QUIC 及 HTTP/3 介绍
QUIC 协议是基于 UDP 的传输层协议,它最显著的改变包括以下几个方面:
把复用移到了传输层
简化 HTTP:直接将连接复用机制放置在 QUIC 协议内来处理,简化了 HTTP 层面。
使用新的传输层协议
解决队头堵塞:使用全新的传输层协议 UDP,解决队头堵塞问题。
TLS 已被包括(不再是单独一层):把 TLS 直接嵌入在 QUIC 协议里,而不是单独一层实现。
连接迁移:在 QUIC 协议里不再依赖于四元组标记连接,而是使用 Connection ID 标记连接。只要保持 Connection ID 不变,即使改变原地址和源端口依旧可以保持原有连接。
在用户空间实现而不是内核:QUIC 协议是在 Linux 的用户空间,而不是内核实现的。这样的好处是我们可以更加快速地迭代,不必依赖于内核的一些升级。
HTTP 语义保持不变
GET 依旧是 GET
Headers 也还是 Headers
虽然目前可能有 40% 的网站支持 HTTP/2 ,接近 25% 的网站支持 HTTP/3,但是在实际部署情况中,对于 HTTP/2 和 HTTP/3 的支持,可能并不是真实的 Web 服务器或者应用服务器支持,而是依赖于前端类似 NGINX 这样的一个反向代理,或者是互联网 CDN 这样的技术进行支持,这也使得应用还可以保持 HTTP/1 的协议不变。
这主要是因为 HTTP/2 和 HTTP/3 所做的改进更多是为了增加互联网传输效率,主要是在互联网使用,而在内网环境一般都会有高速可靠的一个网络连接,所以并不会使用 HTTP/2 和 HTTP/3 从而增加开发难度。
NGINX 对 QUIC 和 HTTP/3 的支持
单独的 QUIC 分支进行开发:目前 NGINX 对 QUIC 的支持是使用了一个单独的分支进行开发,您可以点击 NGINX— QUIC 版本下载进行测试及使用。
不同的模块实现:QUIC 和 HTTP/3 的会在不同的模块进行实现。QUIC 的支持会在 core 模块实现,HTTP/3 的支持会在 http_v3_module 模块实现。
更多的 TLS 支持:TLS 支持使用 BoringSSL、LibreSSL 或者 OpenSSL 的 quic tls fork。
支持连接迁移:为了在 NGINX 多进程的架构下支持连接迁移,NGINX 研发团队开发了一个 eBPF 项目来支持 QUIC 的连接迁移。
原计划于 2022 年底将 QUIC 分支 Merge 到主线版本。
在配置 HTTP/3 时,除了反向代理节点需支持 QUIC 和 HTTP/3 协议外,还需要解决如何同客户端协商的问题。众所周知,从 HTTP/1 升级到 HTTP/2 只需要进行协议升级就可以,但是 HTTP/3 使用了基于 UDP 的 QUIC 协议,所以用户除非使用专属客户端,否则浏览器默认并不会在开始的时候向服务端发起 UDP 连接请求。
所以要去支持 QUIC 和 HTTP/3 协议,还需要拥有一个 HTTP/1 或者 HTTP/2 的服务进行兜底,保证可以先处理客户端默认发过来的基于 TCP 的连接请求。
服务端再在 Response 中加入类似于 Alt-Svc: h3=":443" 的 Header 去通知客户端支持 HTTP/3 协议以及使用的端口,进而使后续的服务请求可以使用 QUIC 协议。
接下来是具体的 NGINX 配置的情况。一定要使用 NGINX QUIC 的分支编译,还需要加入 HTTP/3 的 module。目前核心的指令为两条,首先需要增加一个基于 UDP 的 Listener,同时要加入 reuseport 参数来支持连接迁移机制。
其次需要在响应里加入一个 Header,使客户端可以及时接收到服务端支持 HTTP/3 协议,明确支持端口,保证客户端可以通过相应的 UDP 端口来发起 QUIC 连接。
NGINX 唯一中文官方社区 ,尽在 http://nginx.org.cn/
更多 NGINX 相关的技术干货、互动问答、系列课程、活动资源:
评论