革命性的网络编程:Go的QUIC和HTTP/3之旅

注:本文核心内容由大语言模型生成,辅以人工事实核查与结构调整。
Go 语言因其强大的网络编程能力而闻名,如今正踏上整合下一代互联网协议——HTTP/3 及其底层传输协议 QUIC——的重要旅程。这个历程经历了多年社区的期待与战略性开发,预示着 Go 的网络栈将迎来革命性变化。
背景:社区的期待
Go 社区长期以来都在期待官方支持 HTTP/3,这也是近几年最受关注的功能请求之一。早在 2019 年,就有人创建了 #32204 issue 来追踪标准库对 HTTP/3 支持的进展。随着 Chrome、Firefox 等主流浏览器,以及 Cloudflare 等基础设施服务商陆续支持 HTTP/3,这种期待也持续升温。
尽管社区呼声很高,Go 团队依然采取了谨慎的态度。他们主要顾虑包括:
QUIC 和 HTTP/3 IETF 标准的稳定性(RFC 9000 和 RFC 9114)。过早实现可能会导致后期大规模重构。
API 设计的复杂性。新的 QUIC 概念(如连接、流、0-RTT 零往返时延)如何与 Go 现有的
net.Conn、net.Listener架构兼容,是一个棘手问题。实现高性能、安全的 QUIC 协议栈的难度。这涉及流量控制、拥塞控制、丢包恢复等复杂机制,增加了实现的挑战。
Go 团队战略:两步走
随着 QUIC 标准化完成,以及 QUIC 支持被集成进 crypto/tls,Go 团队基于明确的 “两步走”战略 启动了官方实现计划。
第一步:构建 QUIC 基础 (x/net/quic)
第一阶段的重点是开发 golang.org/x/net/quic 中的基础 QUIC 协议实现。这项工作由 proposal #58547 追踪,是支持 HTTP/3 的前置条件。x/net/quic 包已从内部包转为公开包,显示出其逐渐成熟,尽管仍标注为实验性,API 未来可能会有变化。
x/net/quic 引入的核心 API 概念包括:
Endpoint(原 Listener):用于在某个网络地址上监听 QUIC 流量。
Conn:表示一个客户端与服务端之间的 QUIC 连接,能够承载多个流。
Stream:有序、可靠的字节流,类似 TCP 连接,可进行读写操作。
下面是一些与 x/net/quic 交互的 Go 代码示例:
1 | // 客户端发起连接 |
需要注意的是,Go 官方实现 并没有直接采用流行的第三方库 quic-go 的代码。原因包括:API 设计理念的差异、代码风格和测试框架的不同,以及官方认为“从零实现”更有利于长期维护。
第二步:实现 HTTP/3 (x/net/http3)
在 x/net/quic 基础之上,proposal #70914 正式启动了 x/net/http3 的开发。与 x/net/quic 类似,HTTP/3 的实现最初也会位于内部包(x/net/internal/http3),待 API 稳定和最终审查后才会迁移到公共包。代码变更显示,目前的工作重点包括 QPACK(HTTP/3 的头部压缩算法)、Transport、Server 以及请求/响应体的传输机制。
对 Go 网络编程的影响
官方 QUIC 和 HTTP/3 支持的到来,将为 Go 开发者带来革命性的变化:
透明的协议升级:预计未来
net/http包将像集成 HTTP/2 一样,无缝支持 HTTP/3。这意味着开发者可能仍然可以直接使用http.Get("https://example.com/")这样的调用,而底层系统会自动通过 UDP 上的 QUIC 进行通信,而无需修改代码。解决队头阻塞问题:HTTP/3 的最大优势之一就是能够缓解 TCP 的队头阻塞(HOL blocking)。在 HTTP/2 中,如果某个流上的一个数据包丢失,TCP 的丢包恢复会导致所有并发流都被阻塞。而 QUIC 的原生多路复用机制使得丢包只会影响发生丢包的那个流,从而带来更低延迟和更高吞吐量,尤其在网络质量不佳的环境下尤为明显。这对需要处理大量并发请求的 Go 微服务尤其有利。
更快的连接建立:QUIC 支持的 0-RTT(零往返时延)连接建立 能显著减少握手延迟,这对需要频繁建立新连接的应用非常关键。
原生多路复用传输层:超越 HTTP/3,本地化的 QUIC API 将为更多高级通信协议铺平道路,例如 基于 QUIC 的 gRPC 和 WebTransport,也为需要多路复用和低延迟通信的自定义协议带来可能性。
最终愿景:Linux 内核中的 QUIC
虽然 x/net/quic 的开发代表了用户态的重要一步,但 QUIC 的最终愿景是在 Linux 内核中获得原生支持。Xin Long 已经提交了相关补丁,推动 QUIC 内核实现进入主线。
为什么要在内核中集成 QUIC?
将 QUIC 从用户态库(如 x/net/quic 或 quic-go)迁移到内核有几个关键优势:
极致性能潜力:内核实现可以利用现代网络硬件的协议卸载能力,如通用分段卸载(GSO)和通用接收卸载(GRO)。这将显著降低处理大量小 UDP 包时的 CPU 开销,达到用户态实现难以企及的性能水平。
更广泛的可用性:一旦 QUIC 成为内核支持的协议(例如
IPPROTO_QUIC),任何应用都可以通过标准的socket()系统调用使用它,就像使用 TCP 或 UDP 一样,而无需依赖特定的用户态库。统一的生态系统:内核级支持将促进更一体化的生态环境,惠及 Samba、NFS、curl 等项目。对 Go 开发者来说,这意味着标准库和底层系统调用都可以普遍利用 QUIC 的优势。
当前实现与挑战:
内核实现的目标是高度集成,允许开发者使用熟悉的 API 创建 QUIC 套接字,例如:
1 | socket(AF_INET, SOCK_STREAM, IPPROTO_QUIC) |
并结合 bind()、connect()、listen()、accept() 等调用。复杂的 TLS 握手与证书验证逻辑仍会保留在用户态,类似于内核 TLS(kTLS),而握手完成后数据加解密由内核接管。
初步基准测试表明,内核实现的性能仍低于 kTLS 或原生 TCP,原因包括:缺乏硬件卸载支持、额外的内存拷贝、以及 QUIC 头部加密的开销。但随着实现的逐步完善,以及硬件厂商提供更多支持,这一差距预计将缩小。完整的内核态 QUIC 集成预计最早也要到 2026 年 才能实现。
quic-go(第三方库)
在 Go 官方支持 QUIC 和 HTTP/3 之前,第三方库 quic-go(由 Marten Seemann 维护)成为 Go 生态中事实上的标准实现。它被描述为一个 “生产可用的纯 Go 实现的 QUIC”,为包括 Caddy Web 服务器在内的多个项目提供了关键的 QUIC 与 HTTP/3 支持。
quic-go 实现了核心 QUIC 协议(RFC 9000、RFC 9001、RFC 9002)和 HTTP/3(RFC 9114),并包含 QPACK(RFC 9204)和 HTTP 数据报(RFC 9297)。它还支持多个其他 RFC 和草案,例如:
不可靠数据报扩展(RFC 9221)
DPLPMTUD(RFC 8899)
QUIC v2(RFC 9369)
使用 qlog 的 QUIC 事件日志
带部分传输的 QUIC 流重置
此外,通过 webtransport-go 还可以使用基于 HTTP/3 的 WebTransport。
开发者可以使用 quic-go 配置一个 HTTP/3 传输,并将其交给常规的 http.Client 发起 HTTP/3 请求。在 quic-go 仓库中提供了相应的示例。不过需要注意的是,quic-go 的客户端专门用于 QUIC 传输,不会自动回退到 HTTP/2 或 HTTP/1。
下面是一个使用 quic-go 配置 http.Client 的示例:
1 | // 这是一个概念性示例,基于源码。 |
HTTP/3 概述
HTTP/3 是超文本传输协议的第三个主要版本,旨在提升 Web 信息交换的效率。与依赖于 TCP 的前两代协议(HTTP/1.1 和 HTTP/2)不同,HTTP/3 使用 QUIC——一种基于 UDP 的多路复用传输协议。HTTP/3 于 2022 年 6 月发布为 RFC 9114,其底层依托于 QUIC 协议(RFC 9000 及相关 RFC)。
在语义层面上(如请求方法、状态码、消息字段),HTTP/3 与前代保持一致,但在数据编码和会话状态维护方式上进行了根本性变革。通过采用 QUIC,HTTP/3 在真实场景中带来了显著优势,包括更低延迟和更快加载速度,在某些情况下比 HTTP/1.1 快四倍以上。尤其在高丢包或不稳定网络环境下优势更为明显。
协议的核心创新在于其解决了 TCP 的队头阻塞问题。HTTP/3 的原生多路复用机制确保丢失的数据包只会影响所属的具体流,而不会阻塞整个连接中的所有事务。此外,QUIC 还支持 0-RTT 连接建立,进一步减少握手延迟,加快交互速度。
HTTP/3 已实现快速普及:截至 2024 年 9 月,超过 95% 的主流浏览器支持该协议。Chromium 系列浏览器(Google Chrome、Microsoft Edge、Opera、Samsung Internet)在 2020 年 4 月已默认启用,Mozilla Firefox 于 2021 年 5 月跟进,Safari 14 在 2020 年 9 月加入支持,并自 2024 年 9 月的 Safari 16 起对所有用户开放。HTTP/3 目前被 全球前 1000 万网站中的 34% 使用。
HTTP/3 实现(库与服务器)
HTTP/3 的重要性不断提升,推动其在多种编程语言库和主流 Web 服务器中的实现:
库
C:
lsquic(LiteSpeed)、nghttp3、libcurl、MsQuic(微软)**C++**:
proxygen(Facebook)、Cronet(Google)**C#**:
.NET(基于 MsQuic)Go:
quic-goHaskell:
http3Java:
Kwik、FlupkePython:
aioquicRust:
quiche(Cloudflare)、neqo(Mozilla)、quinn、s2n-quic(AWS)
服务器
LiteSpeed Web Server:自 6.0.2 版本(2021 年 6 月)起默认启用 HTTP/3。
Caddy Web Server:自 2.6.0 版本(2022 年 9 月)起默认启用 HTTP/3。
Nginx:自 1.25.0 版本(2023 年 5 月)起支持 HTTP/3,最早的技术预览发布于 2020 年 6 月。Cloudflare 也提供了集成其
quiche库的 Nginx 补丁。Microsoft IIS:在 Windows Server 2022 和 Windows 11 中原生支持 HTTP/3。
HAProxy:自 2.6 版本(2022 年 5 月)起支持基于 QUIC 的 HTTP/3。
Nimble Streamer:自 4.1.8-1 版本(2025 年 2 月)起支持基于 HTTP 的协议使用 HTTP/3。
参考
- Excerpts from “A production-ready QUIC implementation in pure Go - GitHub” - https://github.com/quic-go/quic-go
- Excerpts from “Go官方HTTP/3 实现终迎曙光:x/net/http3 提案启动,QUIC 基础已就位 - Tony Bai” - https://tonybai.com/2025/08/02/proposal-http3
- Excerpts from “HTTP/3 - Wikipedia” - https://en.wikipedia.org/wiki/HTTP/3
- Excerpts from “How can I make an http3 request from golang? - Reddit” - https://www.reddit.com/r/golang/comments/1359c2b/how_can_i_make_an_http3_request_from_golang/
更多内容
最近文章:
随机文章:
更多该系列文章,参考medium链接:
https://wesley-wei.medium.com/list/you-should-know-in-golang-e9491363cd9a
English post: https://programmerscareer.com/golang-quic-start/
作者:微信公众号,Medium,LinkedIn,Twitter
发表日期:原文在 2025-09-07 16:05 时创作于 https://programmerscareer.com/zh-cn/golang-quic-start/
版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
评论