Async QUIC and HTTP/3 made easy: tokio-quiche is now open-source
六年前,我们推出了用Rust编写的开源QUIC实现quiche。今天我们宣布开源tokio-quiche——这是我们经过实战检验的异步QUIC库,结合了quiche和Rust Tokio异步运行时。tokio-quiche为Cloudflare在Apple iCloud Private Relay中的Proxy B以及我们基于Oxy的下一代代理提供支持,以低延迟和高吞吐量处理每秒数百万个HTTP/3请求。tokio-quiche还为Cloudflare Warp的MASQUE客户端提供支持,用基于QUIC的隧道替代了我们的WireGuard隧道,并支持异步版本的h3i。
quiche是作为sans-io库开发的,这意味着它实现了处理QUIC传输协议所需的状态机,但不对用户执行IO的方式做任何假设。这意味着,只要有足够的努力,任何人都可以使用quiche编写IO集成!这包括连接或监听UDP套接字,管理在该套接字上发送和接收UDP数据报,同时将所有网络信息提供给quiche。考虑到我们需要这种集成是异步的,我们必须在与异步Rust运行时集成的同时完成所有这些工作。tokio-quiche为您完成了所有这些工作,无需额外努力。
降低入门门槛
最初,tokio-quiche仅用作Oxy的HTTP/3服务器的核心。但将tokio-quiche创建为独立库的契机是我们需要支持MASQUE的HTTP/3客户端。我们的Zero Trust和隐私团队分别需要MASQUE客户端通过WARP和隐私代理隧道传输数据,我们希望使用相同的技术来构建客户端和服务器。
我们最初开源quiche是为了与尽可能多的利益相关者分享我们的内存安全QUIC和HTTP/3实现。当时我们的重点是低层级、sans-io的设计,可以集成到多种类型的软件中并广泛部署。我们实现了这个目标,quiche已部署在许多不同的客户端和服务器中。然而,将sans-io库集成到应用程序中是一个容易出错且耗时的过程。我们开发tokio-quiche的目标是通过提供大部分所需代码来降低入门门槛。
如果希望与我们产品和系统交互的其他方不采用HTTP/3,仅Cloudflare拥抱HTTP/3并没有太大用处。开源tokio-quiche使得与我们的系统集成更加直接,并有助于推动行业进入HTTP的新标准。通过将tokio-quiche贡献回Rust生态系统,我们希望促进HTTP/3、QUIC和新的隐私保护技术的开发和使用。
层层递进的执行器模型
Tokio是一个非常流行的异步Rust运行时。它高效地管理、调度和执行在我们边缘运行的数十亿个异步任务。我们在Cloudflare广泛使用Tokio,因此我们决定将quiche与其紧密集成——因此得名tokio-quiche。在底层,tokio-quiche使用执行器来驱动QUIC和HTTP/3状态机的不同部分。执行器是具有内部状态的小型任务,通常使用通过通道的消息传递与外部世界通信。
由于两者在概念上的相似性,执行器模型是用于异步化sans-io库的绝佳抽象。执行器和sans-io库都有某种内部状态,它们希望独占访问。它们通常都通过发送和接收"消息"与外部世界交互。quiche的"消息"实际上是表示传入和传出网络数据的原始字节缓冲区。tokio-quiche的"消息"之一是描述传入UDP数据包的Incoming结构体。由于这些相似性,异步化sans-io库意味着:等待新消息或IO,将消息或IO转换为sans-io库理解的内容,推进内部状态机,将状态机的输出转换为消息或IO,最后发送消息或IO。
tokio-quiche中的主要执行器是IO循环执行器,它在quiche和套接字之间移动数据包。由于QUIC是一种传输协议,它可以承载您想要的任何应用协议。HTTP/3非常常见,但基于QUIC的DNS和即将推出的基于QUIC的媒体传输是其他例子。甚至有一个RFC可以帮助您创建自己的QUIC应用!tokio-quiche暴露了ApplicationOverQuic特质来抽象应用协议。该特质抽象了quiche的方法和底层I/O,让您可以专注于应用逻辑。例如,我们的HTTP/3调试和测试客户端h3i就是由一个专注于客户端的、非HTTP/3的ApplicationOverQuic实现提供支持的。
tokio-quiche附带了一个专注于HTTP/3的ApplicationOverQuic,称为H3Driver。H3Driver将quiche的HTTP/3模块连接到这个IO循环,为异步HTTP/3客户端或服务器提供构建块。该驱动程序将quiche的原始HTTP/3事件转换为高层级事件和异步主体数据流,让您可以相应地响应它们。H3Driver本身是通用的,暴露了ServerH3Driver和ClientH3Driver变体,每个变体都在核心驱动程序的事件之上堆叠了额外的行为。
在tokio-quiche内部,我们生成了两个重要的任务来促进数据从套接字移动到quiche。第一个是InboundPacketRouter,它拥有套接字的接收部分,并通过其连接ID将入站数据报路由到每个连接的通道。第二个任务,IoWorker执行器,是前面提到的IO循环,并驱动单个quiche连接。它将quiche调用与ApplicationOverQuic方法交织在一起,确保您可以在任何IO交互之前和之后检查连接。
更多关于创建tokio-quiche的博客文章即将发布。我们将讨论执行器模型和互斥锁、UDP GRO和GSO、tokio任务协作预算等等。
下一步:更多关于QUIC及更高层次的内容!
tokio-quiche是Cloudflare对Tokio的QUIC和HTTP/3生态系统投资的重要基础——但它仍然只是一个具有自身复杂性的构建块。未来,我们计划发布同样易于使用的HTTP客户端和服务器抽象,这些抽象如今为我们的Oxy代理和WARP客户端提供支持。请继续关注Cloudflare关于QUIC和HTTP/3的更多博客文章,包括为我们隐私代理客户提供的开源客户端,以及一个使用tokio-quiche处理每秒数百万次请求的全新服务!
现在,请查看crates.io上的tokio-quiche crate和GitHub上的源代码,构建您自己的QUIC应用程序。可以是一个简单的回声服务器、一个基于QUIC的DNS客户端、一个自定义VPN,甚至是一个功能齐全的HTTP服务器。也许您会抢先一步?