1. 1
  2. 2
  3. 3
  4. 4
  5. 5

# теория · шаг 1 из 5

Почему понадобился QUIC

Коротко

HTTP/2 упирается в TCP: одна потеря тормозит все потоки сразу. QUIC поверх UDP ведёт надёжность для каждого потока отдельно.

  • Замер: при потерях на стороне данных медиана HTTP/2 - 2021 мс против 1237 у шести соединений HTTP/1.1, а хвост уходит за пять секунд.
  • QUIC встраивает TLS 1.3, экономит круговой обход на рукопожатии (замер: 719 против 814 мс) и переживает смену сети.
  • Но выигрыш на потерях воспроизвести на стенде не удалось - HTTP/3 оказался хуже обоих. Причина в реализации и настройке, а вывод простой: мерь у себя.
  • Цена: блокировки UDP, расход процессора, слепая отладка.

Если знаешь, что такое head-of-line blocking транспорта, - листай до «Теперь сам».

Сначала ответь сам

Человек едет в метро и открывает каталог. Сеть теряет три процента пакетов - для мобильной сети это будни. Что покажет замер: HTTP/2 быстрее шести соединений HTTP/1.1 или медленнее?

Стенд, 30 файлов, задержка 100 мс, потери 3% на стороне ответов, семь прогонов:

протокол прогоны, мс
HTTP/1.1, шесть соединений 1017 1120 1214 1237 1341 1420 1767
HTTP/2, одно соединение 1313 1413 1714 2021 5221 5268 5486

Медленнее. Причём не на проценты, а вдвое по медиане - и с хвостом, где страница грузится пять секунд вместо одной.

На что это похоже

Одна дорога с односторонним движением против шести параллельных улиц. По дороге машины идут строго в том порядке, в каком въехали; сломалась одна - встали все, кто за ней, включая тех, кому надо было свернуть раньше.

На шести улицах поломка останавливает одну шестую движения. Именно поэтому шесть соединений HTTP/1.1 на плохой сети иногда обгоняют одно мультиплексированное.

Механизм: очередь ниже протокола

HTTP/2 поверх TCP поток 1 ждёт поток 2 ждёт, хотя данные уже в буфере ядра поток 3 потерян сегмент - виноват только он HTTP/3 поверх QUIC поток 1 едет дальше поток 3 ждёт только он: порядок ведётся по потокам
TCP гарантирует порядок всего соединения. QUIC - порядок внутри каждого потока.

Заменить TCP нельзя: ядра, роутеры и промежуточные железки за тридцать лет обросли предположениями о нём. Поэтому QUIC построили поверх UDP - простого способа послать пакет без гарантий доставки и порядка (в отличие от TCP). UDP ничего не гарантирует, а значит и не мешает. Всё, что нужно от надёжного транспорта - повторы, порядок, контроль перегрузки, - QUIC реализует сам, отдельно для каждого потока.

Разбор: что QUIC получил заодно

Раз транспорт пишут с нуля, в него сразу встроили то, что раньше было надстройками:

Шифрование не отключается. TLS 1.3 - часть QUIC, а не слой поверх. Открытого QUIC не существует.

Рукопожатие короче. TCP плюс TLS 1.3 - это два круговых обхода до первого байта. QUIC совмещает их в один, и это видно на замере даже без потерь:

↳  вывод30 файлов, задержка 100 мс, сеть чистая, медиана семи прогонов
HTTP/1.1, шесть соединений   821 мс
HTTP/2,   одно соединение    814 мс
HTTP/3,   одно соединение    719 мс

Ровно сто миллисекунд разницы при задержке в сто - это и есть сэкономленный круг.

Соединение переживает смену сети. TCP-соединение опознаётся четвёркой адрес-порт-адрес-порт, поэтому переход с Wi-Fi на LTE его убивает. У QUIC есть Connection ID - идентификатор, не зависящий от адресов: телефон уходит в сотовую сеть, а загрузка продолжается с того же места.

Разбор: обещание, которое стенд не подтвердил

Логика главы требует, чтобы на тех же потерях HTTP/3 обошёл HTTP/2. Замер даёт обратное:

протокол прогоны при потерях 3%, мс
HTTP/1.1, шесть соединений 1017 … 1237 … 1767
HTTP/2, одно соединение 1313 … 2021 … 5486
HTTP/3, одно соединение 2744 … 7532 … 9306

HTTP/3 оказался худшим из трёх. Причину я не устанавливал; правдоподобных несколько, и все они не про сам протокол: QUIC живёт в пользовательском пространстве, на непрогретом пути без quic_gso и без настройки буферов UDP каждая потерянная датаграмма обходится дороже, а сборка клиента и версия серверного модуля тоже свежие.

Полезно тут не число, а вывод: обещание протокола и поведение конкретной сборки на конкретной сети - разные вещи. HTTP/3 включают рядом с HTTP/2 и смотрят на свои метрики, а не на статьи.

Что ломается без этого

UDP режут. Корпоративные сети и часть публичных Wi-Fi блокируют UDP/443 целиком. Протокол это предусматривает - клиент откатывается на TCP, - но именно поэтому HTTP/3 всегда идёт в дополнение к HTTP/2, а не вместо.

Процессор. Шифрование и сборка потоков живут в пользовательском пространстве, без ядерных оптимизаций вроде TSO. На отдаче тяжёлой статики разница видна.

Отладка. tcpdump (программа, показывающая сетевые пакеты) выведет поток UDP-датаграмм - отдельных пакетов - и ничего больше: всё, включая заголовки, зашифровано. Разбирать в Wireshark можно только с экспортированными ключами сессии.

Зачем это в работе

Первое соединение всегда идёт по TCP - иначе клиенту пришлось бы наугад слать UDP-пакеты каждому сайту. О поддержке QUIC сервер сообщает заголовком:

↳  выводcurl -sI https://shop.local/
alt-svc: h3=":443"; ma=86400

Браузер запоминает это на ma секунд и следующее соединение пробует по QUIC, держа наготове TCP. Без Alt-Svc (или соответствующей DNS-записи HTTPS) HTTP/3 может быть идеально настроен - и не использоваться никем.

Модуль до сих пор называется экспериментальным

ngx_http_v3_module появился в 1.25.0, живёт в стабильной ветке и работает в проде у многих - но в документации по-прежнему написано «экспериментальная поддержка», а по HTTP/3 регулярно выходят исправления безопасности: в 1.31.2 закрыли use-after-free при обработке QUIC-сессии (CVE-2026-42530), в 1.30.1 - подмену адреса при миграции соединения. Включаешь HTTP/3 - подписывайся на обновления.

Теперь сам

Коллега предлагает: «раз QUIC лучше на потерях, давай оставим только его и уберём TCP - меньше портов, меньше настроек». Что возразить?

Три вещи. Первая: часть сетей режет UDP/443 целиком, и для их пользователей сайт просто исчезнет - отката на TCP не останется. Вторая: браузер узнаёт про HTTP/3 из заголовка Alt-Svc, который приходит по TCP; без первого TCP-соединения он и не догадается пробовать QUIC. Третья: «лучше на потерях» - это обещание протокола, а замер выше показывает, что конкретная сборка может вести себя иначе.

Главное

HTTP/2 упирается в очерёдность TCP: замер при потерях даёт медиану вдвое хуже шести соединений HTTP/1.1 и хвост за пять секунд. QUIC поверх UDP ведёт надёжность отдельно по каждому потоку, встраивает TLS 1.3, экономит круговой обход на рукопожатии (719 против 814 мс на чистой сети) и переживает смену сети благодаря Connection ID. Но выигрыш на потерях зависит от реализации и настройки: на стенде HTTP/3 оказался медленнее обоих, поэтому его включают рядом с HTTP/2 и проверяют по своим метрикам. Цена - блокировки UDP, расход процессора и слепая отладка.

Комментарии

Пока нет комментариев. Будь первым!

Оставить комментарий

Комментарий появится после проверки. Email не публикуется. Войти, чтобы не вводить имя каждый раз.