Сети и протоколы
HTTP/3 и QUIC: изоляция потерь на уровне потока
HTTP/2 исправил очередь на уровне приложения. TCP вернул ту же очередь на уровне байт. Ответ HTTP/3: выбросить TCP полностью и пересобрать надёжность на UDP — по-потоково, не по-соединению. Один потерянный пакет тормозит один поток, а не пятьдесят.
Почему QUIC вместо TCP
TCP гарантирует упорядоченную доставку. Пакет с байтами 1000–1099 потерян. TCP держит в буфере байты 1100–1199, ожидая повторной передачи. Только после её прихода приложение получает байты 1100+. На HTTP/2-уровне — поток #1 использует байты 1000–1099, поток #2 — 1100–1199: оба блокируются, хотя данные потока #2 уже пришли.
QUIC (RFC 9000) построен на UDP и переосмысляет надёжность на уровне потока:
- QUIC нумерует пакеты, не байтовые смещения единого потока. Каждый пакет несёт фреймы из одного или нескольких потоков, каждый фрейм с stream ID и смещением.
- Восстановление потерь per-stream. Когда пакет N потерян, повторно передаются только те потоки, чьи данные были в пакете N. Потоки в других пакетах продолжают работу.
- TLS 1.3 встроен в QUIC. QUIC-хендшейк и TLS-хендшейк происходят вместе — нет отдельного TCP-хендшейка затем TLS-хендшейка. Холодное QUIC-соединение стоит 1 RTT; с session resumption — 0 RTT для данных.
- QUIC транспорт
- UDP порт 443 (по соглашению)
- Холодная QUIC-установка
- 1 RTT (TLS 1.3 встроен)
- 0-RTT resumption
- 0 RTT для данных запроса (с session ticket)
- HTTP/3 потоков на соединение
- 1000+ (конфиги CDN)
- HTTP/3 доля трафика (апрель 2026)
- 21.1% (Cloudflare Radar)
- Поддержка HTTP/3 на сайтах
- 38.8% сайтов (W3Techs, апрель 2026)
QPACK: сжатие заголовков без связи потоков
HTTP/3 заменяет HPACK на QPACK (RFC 9204). Проблема HPACK на QUIC: динамическая таблица упорядочена — если HEADERS-фрейм добавляющий индекс 60 приходит не в порядке (потерян или запоздал), все HEADERS ссылающиеся на индекс 60 блокируются. На TCP это незаметно; на QUIC-потоках это сломало бы изоляцию потоков.
Решение QPACK: вынести обновления динамической таблицы в отдельный управляющий поток. Обычные HEADERS-фреймы на потоках запросов ссылаются только на записи, которые кодировщик знает уже подтверждёнными декодером. HEADERS потока #3 никогда не блокируется обновлениями таблицы потока #1.
Статическая таблица QPACK содержит 99 прединдексированных записей (против 61 у HPACK), покрывая ещё больше общих заголовков.
Миграция соединения
QUIC-соединения идентифицируются connection ID — токеном выбранным при установке — а не 4-tuple (src IP, src port, dst IP, dst port). Когда мобильное устройство переключается с Wi-Fi на LTE (меняется IP), QUIC-соединение может мигрировать:
- Клиент отправляет PATH_CHALLENGE с нового IP.
- Сервер валидирует и отвечает PATH_RESPONSE.
- Соединение продолжает без повторного хендшейка.
HTTP/2 поверх TCP потеряет соединение при смене IP — 4-tuple меняется, TCP-соединение сбрасывается, нужен новый хендшейк (1–2 RTT). Для мобильных пользователей миграция QUIC — ощутимый выигрыш при смене сети.
Согласование версии HTTP/3
HTTP/3 нельзя согласовать только через ALPN — QUIC-пакеты идут по UDP, а многие файрволы блокируют UDP/443. Два способа обнаружения:
- Alt-Svc заголовок: ответ HTTP/1.1 или HTTP/2 содержит
Alt-Svc: h3=":443"; ma=86400. Браузер сохраняет подсказку и пробует HTTP/3 при следующей навигации к этому origin (в пределахmaсекунд). - HTTPS / SVCB DNS-записи (RFC 9460): сервер публикует DNS-запись с поддержкой HTTP/3, и браузеры могут попробовать его даже при первом соединении.
При первой навигации браузер использует TCP-based HTTP/1.1 или /2, узнаёт о /3 через Alt-Svc, затем пробует /3 при следующих. Если /3 не работает (UDP заблокирован), браузер молча фолбечится на /2.
Трассировка загрузки страницы браузером по HTTP/3.
0-RTT resumption
QUIC наследует 0-RTT resumption TLS 1.3: если у клиента есть session ticket от предыдущего соединения, первый QUIC-пакет может нести данные приложения (HTTP-запрос) вместе с материалом TLS-хендшейка. Экономит один RTT — значимо на межконтинентальных линках (100–300 мс).
То же предостережение что и для TLS 1.3 0-RTT: данные 0-RTT воспроизводимы. Сетевой атакующий может переиграть первый пакет. Серверы должны принимать 0-RTT только для идемпотентных методов (GET, HEAD). Для небезопасных методов (POST) современные стеки отвечают 425 Too Early.
Почему QUIC нумерует пакеты, а не байтовые смещения для восстановления потерь?
Что браузер делает при первом посещении сайта с доступным HTTP/3?
Расставьте события HTTP/3-соединения после того как браузер сохранил Alt-Svc h3-подсказку:
- 1 DNS-запрос разрешает IP origin
- 2 Браузер открывает QUIC-соединение (UDP) на порт 443
- 3 QUIC Initial-пакет несёт TLS ClientHello с key shares
- 4 Сервер отвечает: TLS ServerHello + QUIC SETTINGS
- 5 Хендшейк завершается за 1 RTT (или 0 RTT при resumption)
- 6 Браузер отправляет HEADERS-фреймы для ресурсов страницы как QUIC-потоки
- 7 Сервер отправляет чередующиеся DATA-фреймы по всем потокам
- 01Почему HTTP/3 использует QPACK вместо HPACK?
- 02Как работает миграция QUIC-соединения и почему это важно для мобильных?
- 03Когда 0-RTT экономит round-trip и когда опасен?
HTTP/3 заменяет TCP на QUIC — транспорт на UDP с интегрированным TLS 1.3 и per-stream восстановлением потерь. Потерянный пакет тормозит только потоки с данными в нём; остальные продолжают — это решает TCP HOL-блокировку. QPACK заменяет HPACK: обновления динамической таблицы идут по отдельному управляющему потоку, HEADERS-фреймы не блокируют друг друга. QUIC connection ID позволяет миграцию соединения при смене IP (Wi-Fi → LTE) без повторного хендшейка. HTTP/3 обнаруживается через Alt-Svc-заголовки или HTTPS DNS-записи — браузеры молча фолбечатся на HTTP/2 если UDP заблокирован. 0-RTT resumption отправляет данные запроса вместе с хендшейком, но безопасен только для идемпотентных методов.
встречается в5
- MVCC: как Postgres раздаёт согласованные снимкиjunior
- Акт 7 в глубину: шардинг, co-location и семиуровневый каскад трейдоффовmiddle
- Наблюдаемость, антипаттерны и производственный триажsenior
- Raft в реальном мире: partition, медленный диск и клиентская маршрутизацияmiddle
- Raft в production: membership change, Multi-Raft и observabilitysenior