Чуть более 6 лет назад мы представили quiche — нашу реализацию QUIC с открытым исходным кодом, написанную на Rust. Сегодня мы объявляем об открытии исходного кода tokio-quiche, нашей проверенной в боях асинхронной библиотеки QUIC, объединяющей как quiche, так и асинхронную среду выполнения Rust Tokio. Обеспечивая работу Proxy B Cloudflare в Apple iCloud Private Relay и наших прокси следующего поколения на основе Oxy, tokio-quiche обрабатывает миллионы HTTP/3 запросов в секунду с низкой задержкой и высокой пропускной способностью. tokio-quiche также обеспечивает работу клиента Cloudflare Warp's MASQUE, заменяя наши туннели WireGuard на туннели на основе QUIC, и асинхронной версии h3i.
quiche была разработана как sans-io библиотека, что означает, что она реализует конечный автомат, необходимый для обработки транспортного протокола QUIC, не делая никаких предположений о том, как её пользователь намерен выполнять ввод-вывод. Это означает, что приложив достаточно усилий, любой может написать интеграцию ввода-вывода с quiche! Это подразумевает connect или listen на UDP-сокете, управление отправкой и получением UDP-датаграмм на этом сокете с одновременной передачей всей сетевой информации в quiche. Учитывая, что нам нужна асинхронная интеграция, нам пришлось бы делать всё это, интегрируясь с асинхронной средой выполнения Rust. tokio-quiche делает всё это за вас, усилий не требуется.
Снижение порога входа
Изначально tokio-quiche использовалась только как ядро HTTP/3 сервера Oxy. Но толчком к созданию tokio-quiche как самостоятельной библиотеки стала наша потребность в HTTP/3 клиенте с поддержкой MASQUE. Нашим командам Zero Trust и Privacy нужны клиенты MASQUE для туннелирования данных через WARP и наши Privacy Proxies соответственно, и мы хотели использовать одну и ту же технологию для построения как клиента, так и сервера.
Изначально мы открыли исходный код quiche, чтобы поделиться нашей реализацией QUIC и HTTP/3 с защитой от уязвимостей памяти с как можно большим количеством заинтересованных сторон. В то время мы сосредоточились на низкоуровневом дизайне sans-io, который можно интегрировать во многие типы программного обеспечения и широко развернуть. Мы достигли этой цели — quiche развернута во множестве различных клиентов и серверов. Однако интеграция sans-io библиотек в приложения — это подверженный ошибкам и трудоёмкий процесс. Наша цель с tokio-quiche — снизить порог входа, предоставив большую часть необходимого кода самостоятельно.
То, что только Cloudflare внедряет HTTP/3, не имеет особого смысла, если другие, желающие взаимодействовать с нашими продуктами и системами, также не adoptируют его. Открытие исходного кода tokio-quiche делает интеграцию с нашими системами более простой и помогает продвигать отрасль к новому стандарту HTTP. Возвращая tokio-quiche в экосистему Rust, мы надеемся способствовать развитию и использованию HTTP/3, QUIC и новых технологий сохранения конфиденциальности.
tokio-quiche используется внутри компании уже несколько лет. Это дало нам время усовершенствовать и испытать её в боях, продемонстрировав, что она может обрабатывать миллионы RPS. tokio-quiche не предназначена быть автономным HTTP/3 клиентом или сервером, а реализует низкоуровневые протоколы и позволяет создавать более высокоуровневые проекты в будущем. В README содержатся примеры циклов событий сервера и клиента.
Вездесущие акторы
Tokio — это невероятно популярная асинхронная среда выполнения Rust. Она эффективно управляет, планирует и выполняет миллиарды асинхронных задач, работающих на нашем edge. Мы широко используем Tokio в Cloudflare, поэтому мы решили тесно интегрировать quiche с ней — отсюда и название, tokio-quiche. Под капотом tokio-quiche использует акторы для управления различными частями конечного автомата QUIC и HTTP/3. Акторы — это небольшие задачи с внутренним состоянием, которые обычно используют передачу сообщений через каналы для общения с внешним миром.
Модель акторов — это отличная абстракция для асинхронизации sans-io библиотек из-за концептуального сходства между ними. И акторы, и sans-io библиотеки имеют某种 внутреннее состояние, к которому они хотят иметь эксклюзивный доступ. Обычно они взаимодействуют с внешним миром, отправляя и получая «сообщения». «Сообщениями» quiche являются сырые буферы байтов, представляющие входящие и исходящие сетевые данные. Одним из «сообщений» tokio-quiche является структура Incoming, описывающая входящие UDP-пакеты. Из-за этого сходства асинхронизация sans-io библиотеки означает: ожидание новых сообщений или ввода-вывода, преобразование сообщений или ввода-вывода во что-то, что понимает sans-io библиотека, продвижение внутреннего конечного автомата, преобразование вывода конечного автомата в сообщение или ввод-вывод и, наконец, отправку сообщения или выполнение ввода-вывода. (Для более подробного обсуждения акторов с Tokio обязательно ознакомьтесь с превосходной статьёй в блоге Alice Rhyl на эту тему.)
Основным актором в tokio-quiche является актор цикла ввода-вывода, который перемещает пакеты между quiche и сокетом. Поскольку QUIC — это транспортный протокол, он может передавать любой прикладной протокол по вашему желанию. HTTP/3 довольно распространён, но DNS over QUIC и предстоящий Media over QUIC — другие примеры. Существует даже RFC, чтобы помочь вам создать своё собственное приложение поверх QUIC! tokio-quiche предоставляет трейт ApplicationOverQuic для абстрагирования поверх прикладных протоколов. Трейт абстрагирует методы quiche и базовый ввод-вывод, позволяя вам сосредоточиться на логике вашего приложения. Например, наш HTTP/3 клиент для отладки и тестирования, h3i, работает на основе ориентированной на клиент, не-HTTP/3 реализации ApplicationOverQuic.
Диаграмма архитектуры сервера
tokio-quiche поставляется с ориентированным на HTTP/3 ApplicationOverQuic под названием H3Driver. H3Driver подключает HTTP/3 модуль quiche к этому циклу ввода-вывода, чтобы предоставить строительные блоки для асинхронного HTTP/3 клиента или сервера. Драйвер превращает сырые HTTP/3 события quiche в события более высокого уровня и асинхронные потоки данных тела, позволяя вам соответствующим образом на них реагировать. H3Driver сам по себе является обобщённым, предоставляя варианты ServerH3Driver и ClientH3Driver, каждый из которых добавляет дополнительное поведение поверх событий основного драйвера.
Внутренний поток данных
Внутри tokio-quiche мы порождаем две важные задачи, которые облегчают перемещение данных из сокета в quiche. Первая — это InboundPacketRouter, которая владеет принимающей половиной сокета и маршрутизирует входящие датаграммы по их идентификатору соединения (DCID) в канал, специфичный для соединения. Вторая задача, актор IoWorker, — это упомянутый выше цикл ввода-вывода и он управляет одним соединением quiche Connection. Он чередует вызовы quiche с методами ApplicationOverQuic, гарантируя, что вы можете проверить соединение до и после любого взаимодействия ввода-вывода.
Скоро появятся новые статьи в блоге о создании tokio-quiche. Мы обсудим модели акторов и мьютексы, UDP GRO и GSO, бюджетирование кооперации задач tokio и многое другое.
Далее: больше о QUIC и не только!
tokio-quiche — это важный фундамент для инвестиций Cloudflare в экосистему QUIC и HTTP/3 для Tokio — но это всё ещё лишь строительный блок со своей собственной сложностью. В будущем мы планируем выпустить те же простые в использовании абстракции HTTP-клиента и сервера, которые сегодня обеспечивают работу наших прокси Oxy и клиентов WARP. Следите за новыми статьями в блоге о QUIC и HTTP/3 в Cloudflare, включая клиент с открытым исходным кодом для клиентов наших Privacy Proxies и совершенно новую службу, обрабатывающую миллионы RPS с помощью tokio-quiche!