HTTP/3 over QUIC concept page. QUIC = TCP + TLS 1.3 + multiplexing rebuilt over UDP. HTTP/3 is HTTP semantics on QUIC. Wins: no TCP head-of-line blocking, 1-RTT (or 0-RTT) handshake, connection migration, encrypted headers (anti-ossification). Costs: middlebox UDP/443 blocks, higher CPU. Used in Google (gQUIC since 2014), Cloudflare (quiche), Facebook (mvfst), CloudFront. Three scenarios: HTTP/2 HoL blocking vs HTTP/3 per-stream isolation, connection migration WiFi->LTE without reset, 0-RTT resumption with replay-risk caveats.
TCP родом из 1981 года. Он работает — но в современном мире mobile-сетей, edge CDN и приложений с десятками параллельных запросов он начал заметно мешать. Главные боли:
(src_ip, src_port, dst_ip, dst_port). Меняется любой компонент — старое соединение мёртво. Телефон переключился с Wi-Fi на LTE — нужно пересоздавать TCP+TLS state с нуля, потерять playback-буфер видео, заново аутентифицироваться.QUIC решает эти четыре проблемы разом. HTTP/3 — это просто HTTP-семантика, перенесённая поверх QUIC. Если вы строите CDN, mobile-приложение, видеостриминг, голосовой/видеочат, или мультиплексируете много мелких запросов — это ваш транспорт.
«QUIC = TCP + TLS 1.3 + multiplexing, переписанные с нуля поверх UDP в user-space. HTTP/3 = HTTP-семантика на QUIC. Главные подарки: per-stream loss recovery (нет TCP HoL), 1-RTT handshake (0-RTT для repeat visits), connection migration по Connection ID, зашифрованные заголовки пакетов (anti-ossification).»
Почему именно поверх UDP, а не «новый TCP»: UDP проходит через 99% middleboxes, никто не пытается его «оптимизировать», итерировать протокол можно в user-space библиотеке вместе с приложением (а не дожидаться нового kernel-релиза).
Сцена — типичный путь HTTP/3-запроса с мобильного устройства до origin через CDN:
browser + quic-stack. QUIC живёт в user-space внутри клиента, поэтому показан отдельной нодой: важно, что это не kernel-сокет, а пользовательская библиотека (Chrome — quiche/Cronet, Firefox — Necko, Safari — Network.framework).wifi и lte как два параллельных пути. Это ключ к сценарию миграции: оба пути доступны одновременно, и QUIC может переключаться между ними не разрывая connection.edge-server (Cloudflare / Fastly / CloudFront) терминирует HTTP/3 и говорит с origin по «классическому» HTTP/2 over TCP. В реальном мире 99% HTTP/3-трафика терминируется именно на edge, а не на origin — origin обычно отстаёт по HTTP/3-adoption на годы.origin-server, обычный backend.Edges все нарисованы как физические соединения. Ответы в анимациях идут по тем же edges в обратном направлении (reverse-animation), новых edges под ответы не создаём.
На ноде browser зашиты три ADR с обоснованием ключевых компромиссов: когда вообще включать HTTP/3, как обращаться с 0-RTT, и в каких условиях connection migration работает.
Грузим страницу с тремя ресурсами: index.html, app.js, logo.png. В HTTP/2 они идут как три stream'а на одном TCP. Теряется один сегмент с байтами js — kernel TCP HOLDS все последующие сегменты, включая уже прибывший html и png, пока retransmit не заполнит дыру. На 200ms-RTT мобильнике это ~30ms застоя для всей страницы.
Тот же сценарий на HTTP/3: каждый ресурс = свой QUIC stream со своим packet-number space. Теряется пакет stream-3 (js) — streams 1 (html) и 5 (png) доезжают и сразу отдаются приложению, парсер начинает работу, png декодируется. Только js stream ждёт retransmit. Google измерил 3-15% улучшения page-load на YouTube mobile после включения HTTP/3 (Langley et al., SIGCOMM 2017) — это и есть выигрыш от снятия HoL на транспорте.
Это самая важная идея. TCP даёт ordered byte stream per connection; QUIC даёт ordered byte stream per stream. Loss isolation — то, ради чего вообще затевался переход на UDP.
Пользователь качает видео на Wi-Fi, 30 из 50 MB уже на диске. Выходит из зоны Wi-Fi — телефон мигрирует на LTE, получает от оператора новый src-IP.
В TCP это смерть соединения: 4-tuple изменился, kernel шлёт RST, приложение перезапускает download либо с нуля, либо с HTTP-Range-чекпоинта в лучшем случае.
В QUIC connection идентифицируется не 4-tuple, а 64-битным Connection ID (0xDEADBEEF в сценарии), который клиент выбрал в начале сессии. QUIC-стек видит смену маршрута через OS, посылает следующий пакет с того же Connection ID, но с новым src-IP. Edge получает пакет, узнаёт Connection ID в таблице активных соединений, делает анти-spoofing проверку (PATH_CHALLENGE — 8-байтовое случайное значение → PATH_RESPONSE с тем же значением от клиента). 1 RTT на валидацию — и stream продолжает течь с offset 30MB+. Playback не прерывается.
Это mobile-killer feature. WhatsApp, Signal, Meet, FaceTime, YouTube — все опираются на migration для handoff между сетями.
Пользователь был на сайте вчера. QUIC закэшировал PSK и transport parameters. Сегодня кликает ссылку на /article/42.
QUIC-стек шлёт ОДНУ UDP-датаграмму, содержащую сразу: ClientHello (с identity PSK) + 0-RTT-encrypted GET /article/42. Через 50ms edge получает, расшифровывает 0-RTT данные через early-data ключ, проверяет eligibility (метод GET, путь соответствует 0-RTT-allow regex /article/*), сразу из кэша отдаёт статью в 0.5-RTT response. Через 100ms (1 RTT total) браузер рендерит страницу.
Сравнить с TCP+TLS 1.3 = 200ms (1 RTT TCP + 1 RTT TLS), TCP+TLS 1.2 = 300ms. На mobile это разница между «мгновенно» и «заметная пауза».
Цена 0-RTT — отсутствие forward secrecy для early-data и replayability. Поэтому 0-RTT разрешён только для idempotent operations (GET, HEAD), POST/PUT/DELETE деградируются на 1-RTT (HTTP_REQUEST_REJECTED от сервера → клиент ретраит).
Три архитектурных решения, которые автор обязан принять при адаптации QUIC:
ADR-001. Включать HTTP/3 — где это окупается, а где нет. HTTP/3 даёт реальный выигрыш на mobile (per-stream loss recovery, миграция, 0-RTT для repeat-visitors) и для коротких запросов на нестабильной сети. На стабильном wired-канале с длинными соединениями выигрыш минимален, а CPU-стоимость выше (QUIC шифрует каждый пакет в user-space, нет TCP TSO/GRO offload, ~2x CPU при той же пропускной способности). Решение: включать с обязательным HTTP/2 fallback (через Alt-Svc и h3 ALPN) для сервисов с mobile/repeat-visitor трафиком; не включать для server-to-server backhaul внутри датацентра, для captive enterprise-аудитории за UDP/443-блокирующими firewall'ами, и для CPU-bound origin'ов. Never mandatory — ~10% юзеров за корпоративным firewall не получат connection.
ADR-002. 0-RTT — принять surface риска replay. 0-RTT-данные не имеют forward secrecy и поддаются replay-атаке. Решение: включать только для безопасно-идемпотентных GET/HEAD; backend reject'ит 0-RTT для POST/PUT/DELETE/PATCH и для GET, имеющих побочные эффекты (auth callbacks, click trackers, /unsubscribe). PSK ticket lifetime коротким (Cloudflare: ~10s для 0-RTT-eligibility, ~24h для 1-RTT resumption). На financial / health / legal endpoints — 0-RTT off полностью. CDN'ы обычно ship безопасные дефолты; если катите свой стек (mvfst, quiche, ngtcp2) — аудитьте predicate сами.
ADR-003. Connection migration ON для mobile, OFF для stateful backend. Migration работает end-to-end только если LB на edge хэшируется на Connection ID, а не 4-tuple. Cloudflare, Fastly, CloudFront, Envoy 1.22+, HAProxy 2.6+, Google Maglev, Facebook Katran это умеют. Vanilla L4 ECMP-роутеры — нет, они перехэшируют по 4-tuple и сломают migration ещё хуже, чем её отсутствие. Решение: enable migration для client-edge на Connection-ID-aware LB; disable (через disable_active_migration=1 в transport-параметрах) если за вашим QUIC стоит обычный L4-hash балансер. Для internal-DC QUIC между микросервисами — disable, экономит PATH_CHALLENGE round-trip при NAT-rebinding'ах.
quiche; в 2025 ~30% всех HTTP-запросов через них идут по HTTP/3.mvfst, HTTP/3 для всего mobile (Messenger, Instagram, WhatsApp web).103 Early Hints для аналогичного эффекта.Alt-Svc-механизм.disable_active_migration=1.quiche.tls-handshake (как TLS 1.3 reduces до 1 RTT), tcp-handshake (что именно QUIC заменяет), http-protocol (обзор эволюции). Кейсы: cdn-design (HTTP/3 на edge + 0-RTT для repeat visitors), video-streaming (QUIC для LL-HLS / LL-DASH), chat (migration для mobile messengers).