Пора в очередной раз проанализировать, в каком состоянии сейчас находится поддержка HTTP/3 в curl.
Думаю, ситуация с curl отражает положение дел во многих других HTTP-инструментах и библиотеках. HTTP/3 был и продолжает быть более сложным в плане развёртывания по сравнению с HTTP/2.
▍ cURL поддерживает четыре решения HTTP/3 на выбор
Поддержку HTTP/3 в curl можно реализовать с помощью четырёх разных подходов. Мы предоставляем несколько решений, чтобы на «рынке» был выбор, и чтобы они могли «конкурировать» друг с другом, давая пользователям возможность подобрать лучшее. Это избавляет нас от сложной задачи выбирать победителя изначально.
Подробнее обо всех этих четырёх подходах будет сказано ниже.
▍ Почему cURL ещё не использует HTTP/3?
Уже использует, если при сборке этого инструмента включить правильный набор сторонних библиотек. Кроме того, исполняемые файлы curl для Windows, предоставляемые проектом curl, поддерживают HTTP/3.
Для Linux, а также других дистрибутивов и упаковщиков операционных систем серьёзной проблемой остаётся то, что самая популярная библиотека TLS (OpenSSL) не предлагает широко поддерживаемый QUIC API, который предоставляют большинство других библиотек TLS. Напомню, что HTTP/3 задействует протокол QUIC (Quick UDP Internet Connections), внутренне использующий TLS 1.3. Это отсутствие API в OpenSSL вынуждает всех, кто хочет использовать библиотеку QUIC, использовать другую библиотеку TLS. Дело в том, что curl не предусматривает сборки с использованием нескольких библиотек TLS. Включение отдельной библиотеки TLS для QUIC наряду с другими протоколами на основе TLS не поддерживается.
Debian проводит эксперимент по внедрению HTTP/3 в поставляемую ими версию curl путём перехода на GnuTLS (и сборки с использованием ngtcp2 + nghttp3).
▍ Бэкенд HTTP/3
Чтобы curl заговорила на HTTP/3, потребуется три составляющих, а также корректировка кода самой программы:
- поддержка TLS 1.3 для QUIC;
- библиотека протокола QUIC;
- библиотека протокола HTTP/3.
▍ Наглядное представление
Ниже в разных столбцах условной схемы представлены четыре решения HTTP/3, поддерживаемые curl. Все, кроме крайнего правого, считаются экспериментальными.
Поддержка бэкенда HTTP/3 в curl на июнь 2024
Слева направо:
- Библиотека quiche поддерживает QUIC и HTTP/3, а также обеспечивает TLS с помощью BoringSSL.
- msh3 — это ещё одна библиотека HTTP/3, использующая mquic для QUIC и либо семейство форков, либо Schannel для TLS.
- nghttp3 — это библиотека HTTP/3, которая в этой конфигурации использует стек QUIC из OpenSSL, который реализует QUIC и TLS.
- nghttp3 для HTTP/3 с использованием ngtcp2 для QUIC позволяет задействовать различные библиотеки TLS: семейство форков, GnuTLS и wolfSSL. (picotls тоже поддерживается, но сама curl не поддерживает её в качестве дополнительного решения TLS).
▍ ngtcp2 лидирует
Тандем библиотек ngtcp2 и nghttp3 стал первой комбинацией QUIC и HTTP/3, предоставившей уже не бета, а полноценные версии, уверенно работающие с curl. И это основная причина, по которой мы рекомендуем предпочесть именно этот подход.
Также привлекает гибкость представленных этой вертикалью решений TLS, поскольку даёт возможность использовать множество разных библиотек. К сожалению, разработчики OpenSSL решили не участвовать в этой игре, так что в приведённой конфигурации потребуется другая библиотека TLS.
▍ OpenSSL QUIC
В OpenSSL 3.2 была добавлена реализация стека QUIC, миновавшая статус «беты», которую curl может использовать в качестве альтернативного решения. Впоследствии в OpenSSL 3.3 были внесены дополнительные доработки. С начала 2024 года curl можно собирать и использовать для HTTP/3, о чём говорилось выше.
Тем не менее API, предоставляемый OpenSSL для выполнения передачи, неполноценен. В нём не хватает важной функциональности, что делает его неэффективным и иногда вынуждает curl входить в холостые циклы, чтобы определить дальнейшие действия. Этот факт и, возможно, некоторые дополнительные проблемы делают реализацию OpenSSL QUIC значительно медленнее конкурентов. Ещё одна причина рассмотреть использование других решений.
Мы продолжаем общаться с командой OpenSSL о том, что ещё они могут добавить в свой API, чтобы мы могли использовать QUIC эффективно. Надеемся, они всё же внесут необходимые доработки.
Штефан Эйссинг построил хороший сравнительный график, который я взял из его презентации «Performance» (Штефан также писал о производительности h3 ранее). В графике сравнивается три бэкенда curl с поддержкой HTTP/3. (В него не включена msh3, поскольку в curl эта библиотека работает недостаточно хорошо).
Как видно ниже, в нескольких тестовых конфигурациях OpenSSL достигает примерно лишь половины уровня быстродействия в сравнении с другими бэкенд-решениями как в количестве запросов в секунду, так и в скорости передачи. Проверка проводилась на localhost, так что операции передачи, по сути, были привязаны к скорости процессора (cpu-bound).
Производительность бэкенда HTTP/3 в curl, запросов в секунду
Производительность бэкенда HTTP/3 в curl, мегабайтов в секунду
Я считаю, что команде OpenSSL, помимо улучшения API, также нужно поработать над быстродействием QUIC.
▍ quiche и msh3
- quiche по-прежнему отмечена как бета и использует только BoringSSL, что усложняет её применение во многих ситуациях.
- msh3 после недавнего рефакторинга вообще перестала работать в curl.
▍ HTTP/3 нагружает процессор
Это знает любой, кто следит за разработкой протокола. Я из раза в раз говорю об этом в каждой своей презентации, посвящённой HTTP/3. И хотя таких презентаций я провёл уже несколько, мне кажется, что повторять это стоит, и что составленные Штефаном графики отчётливо проясняют ситуацию.
HTTP/3 отличается медленной скоростью передачи, когда выполнение привязано к скорости работы процессора. Естественно, в большинстве ситуаций пользователи к ней не привязаны, поскольку обычно узким местом при передаче выступает ограниченная пропускная способность сети. HTTP/3, как правило, быстрее выполняет рукопожатие — благодаря QUIC — поэтому при передаче через него первый байт зачастую доставляется быстрее, чем через любую другую версию HTTP (по TLS).
Далее мы продемонстрируем всё это наглядно на примере других предоставленных Штефаном графиков, начав с рукопожатий, которые он осуществил со своей машины в Германии. В этих тестах использовалась сборка curl 8.8.0-DEV, предшествовавшая выходу curl 8.8.0.
Скорость выполнения рукопожатия в curl через HTTP/3 и HTTP/1.1
Нет, мы не можем объяснить, почему google.com обрабатывает рукопожатия по HTTP/3 медленнее. Можно добавить, что curl.se обслуживается Fastly CDN, поэтому фактически curl сравнивается в отношении реализаций CDN трёх разных поставщиков.
Скорость передачи по HTTP/3, HTTP/2 и HTTP/1.1 в curl
Опять же, эти передачи привязаны к быстродействию процессора, поэтому реально мы наблюдаем здесь огромный объём лишней работы ЦПУ, необходимой для их осуществления. Если же вы производительностью процессора не ограничены, то передачи, естественно, будут выполняться с одной скоростью, как и в старых версиях HTTP.
Все эти сравнения не являются обобщённой оценкой протокола (если такая вообще возможна) и показывают работу curl в отношении его конкретных версий. Мы не можем сделать вывод, что в коде curl есть проблемы или непродуманные решения, которые бы частично это объяснили. Лично я подозреваю, что хоть нам и есть всегда что доработать, вряд ли здесь скрываются какие-то ощутимые преграды для производительности. Но уверенными в этом быть тоже нельзя.
QUIC в OpenSSL здесь тоже выделяется, причём не самым привлекательным образом.
▍ Распространённость HTTP/3
Данные w3techs, Mozilla и Cloudflare сходятся в том, что около 28-30% веб-трафика на данный момент относится к HTTP/3, что превосходит охват HTTP/1.1.
Интересно в этих 30% то, что все крупные игроки и CDN (Google, Facebook, Cloudflare, Akamai, Fastly, Amazon и так далее) работают по HTTP/3, и я думаю, что все вместе они занимают гораздо больше 30%. Это говорит о том, что есть значительная доля браузерного трафика, который может задействовать HTTP/3, но пока этого не делает. К сожалению, найти этому объяснение возможности у меня нет.
▍ Обзор стека HTTPS
Автор: Дмитрий Брайт