HTTP/3 — это третья большая версия протокола, на котором работает весь веб. Главное в ней не новые заголовки, а смена фундамента: транспорт переехал с TCP на UDP, а поверх него работает новый протокол QUIC. Разберёмся, зачем это сделали, чем оно лучше старых версий и что нужно, чтобы включить HTTP/3 на своём сервере.
Table of contents
Open Table of contents
Коротко о предшественниках
HTTP/1.1 (1997) — одно соединение обслуживает один запрос за раз. Чтобы загрузить страницу с десятками файлов, браузер открывает 6 параллельных TCP-соединений на домен и всё равно упирается в очередь. Отсюда костыли вроде спрайтов и склейки CSS.
HTTP/2 (2015) принёс мультиплексирование: много логических потоков в одном соединении. Стало заметно быстрее, но осталась фундаментальная проблема — она спрятана уровнем ниже, в TCP.
Проблема, которую TCP не может решить
TCP гарантирует доставку байтов строго по порядку. Это и есть слабое место. HTTP/2 шлёт несколько потоков через одно TCP-соединение, но TCP видит не потоки, а единый поток байтов. Стоит потеряться одному пакету — и TCP останавливает выдачу всех данных, что пришли после него, пока потерянный пакет не будет переслан. Даже если эти данные относятся к другим, уже полностью полученным потокам.
Это называется head-of-line blocking (блокировка начала очереди). На быстрой проводной сети незаметно, но на мобильной связи с потерями пакетов HTTP/2 порой ведёт себя не лучше HTTP/1.1.
Что меняет QUIC
QUIC — это транспортный протокол поверх UDP, разработанный изначально в Google и стандартизированный IETF в RFC 9000. UDP не гарантирует ни порядок, ни доставку — всю эту логику QUIC реализует сам, но уже с пониманием потоков. Ключевые отличия:
- Потоки независимы. Потеря пакета в одном потоке тормозит только его. Остальные продолжают идти — head-of-line blocking на транспортном уровне исчезает.
- Шифрование встроено. TLS 1.3 — не отдельный слой сверху, а часть QUIC. Незашифрованного QUIC не существует.
- Быстрое рукопожатие. Установка соединения и TLS объединены в один обмен. Это 1 RTT вместо двух-трёх, а при повторном подключении — 0-RTT: данные летят в первом же пакете.
- Connection ID вместо пары IP+порт. Соединение привязано к идентификатору, а не к адресу. Переключились с Wi-Fi на LTE — соединение живёт, ничего не переустанавливается. Это называется connection migration.
Сравнение в одной таблице
| HTTP/1.1 | HTTP/2 | HTTP/3 | |
|---|---|---|---|
| Год | 1997 | 2015 | 2022 |
| Транспорт | TCP | TCP | QUIC / UDP |
| Мультиплексирование | нет | да | да |
| Head-of-line | да (HTTP+TCP) | да (TCP) | нет |
| Шифрование | опционально | де-факто TLS | обязательно (TLS 1.3) |
| Рукопожатие | 1+ RTT | 1+ RTT | 1 / 0 RTT |
| Смена сети | разрыв | разрыв | бесшовно |
Что нужно, чтобы включить HTTP/3
Хорошая новость: на проде это чаще всего пара строк конфига. Нужны три вещи.
1. Сервер с поддержкой QUIC. Caddy умеет HTTP/3 из коробки. Nginx — начиная с ветки 1.25 (модуль ngx_http_v3_module, сборка с BoringSSL/QUIC). HAProxy, Cloudflare и большинство CDN — тоже умеют.
2. TLS 1.3. QUIC без него не работает. Если у вас уже валидный сертификат и TLS 1.3 включён — этот пункт закрыт.
3. Открытый UDP/443. Самая частая причина «не заводится»: на firewall открыт только TCP/443. QUIC ходит по UDP, его нужно явно разрешить.
Минимальный пример для Caddy — HTTP/3 включён автоматически, отдельных директив не требуется:
example.com {
reverse_proxy localhost:8080
}
Для Nginx 1.25+ включаем quic на listen и анонсируем поддержку клиенту заголовком Alt-Svc:
server {
# TCP для HTTP/1.1 и HTTP/2
listen 443 ssl;
# UDP для HTTP/3 (QUIC)
listen 443 quic reuseport;
ssl_protocols TLSv1.3;
# говорим браузеру: "у меня есть HTTP/3, приходи по нему"
add_header Alt-Svc 'h3=":443"; ma=86400';
server_name example.com;
# ...
}
Не забудьте про firewall:
# открыть UDP/443 для QUIC
sudo ufw allow 443/udp
Как браузеры это используют
Важная деталь: браузер не подключается по HTTP/3 сразу. Первый запрос почти всегда идёт по HTTP/2 поверх TCP. В ответе сервер присылает заголовок Alt-Svc: h3=":443", который означает «меня можно найти и по HTTP/3». Браузер запоминает это и следующие соединения с этим хостом устанавливает уже по QUIC. Поэтому HTTP/3 «включается» со второго визита — это нормально.
Как проверить, что работает
Самый простой способ, работающий с любым curl, — проверить, анонсирует ли сервер HTTP/3 заголовком Alt-Svc:
curl -sI https://example.com | grep -i alt-svc
# alt-svc: h3=":443"; ma=86400
Если заголовок есть — сервер корректно сообщает браузерам о поддержке HTTP/3. Тут не нужен HTTP/3 в самом curl (стоковая сборка из репозиториев Ubuntu/Debian почти всегда собрана без QUIC) — заголовок отдаётся по обычному HTTPS.
Чтобы увидеть реальное HTTP/3-соединение — в DevTools браузера на вкладке Network включите колонку Protocol: у запросов будет значиться h3.
Если своего curl с HTTP/3 под рукой нет, проще всего проверить домен онлайн через http3check.net: вводите адрес сайта — и сервис показывает, поддерживается ли HTTP/3 и QUIC, какие версии QUIC отвечают, какой заголовок Alt-Svc отдаёт сервер, а также детали TLS-сертификата. Удобно, когда нужно убедиться, что HTTP/3 действительно доступен снаружи, а не только в вашей конфигурации.
Стоит ли переходить
Для типичного сайта на быстром проводном интернете разница будет небольшой. Реальный выигрыш HTTP/3 даёт там, где сети ненадёжны: мобильный трафик, далёкие от сервера регионы, частые переключения Wi-Fi/LTE. Меньше RTT на рукопожатии, нет блокировки потоков при потерях, бесшовная смена сети — всё это напрямую улучшает время загрузки на слабой связи.
Риск минимальный: HTTP/3 включается поверх существующих HTTP/2 и HTTP/1.1, а не вместо них. Браузер, который не умеет QUIC (или сеть, где UDP/443 закрыт), просто останется на HTTP/2. Можно включать и наблюдать.
Итог: HTTP/3 — это не косметика, а перенос транспорта с TCP на QUIC/UDP. Платой стало обязательное шифрование и открытый UDP-порт; выигрышем — отсутствие head-of-line blocking, рукопожатие за 0–1 RTT и соединения, переживающие смену сети.