Чем отличаются HTTP/1.1, HTTP/2 и HTTP/3?
HTTP/1.1, HTTP/2 и HTTP/3 — три поколения протокола HTTP, каждое из которых решает проблемы предыдущего: от текстового протокола с блокировкой до бинарного мультиплексированного протокола поверх QUIC.
Сравнительная таблица
| Свойство | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|
| Год стандартизации | 1997 | 2015 | 2022 |
| Транспорт | TCP | TCP | QUIC (поверх UDP) |
| Формат | Текстовый | Бинарный | Бинарный |
| Мультиплексирование | Нет (один запрос за раз на соединение) | Да (множество потоков в одном TCP-соединении) | Да (потоки независимы) |
| Head-of-line blocking | На уровне HTTP и TCP | Решено на уровне HTTP, но остаётся на уровне TCP | Полностью решено |
| Сжатие заголовков | Нет | HPACK | QPACK |
| Server Push | Нет | Да | Да (редко используется) |
| Шифрование | Опционально (HTTPS) | Фактически обязательно | Обязательно (встроено в QUIC) |
| Время установления соединения | 1 RTT (TCP) + 2 RTT (TLS 1.2) | 1 RTT (TCP) + 1 RTT (TLS 1.3) | 1 RTT (QUIC + TLS 1.3), 0-RTT при повторном |
HTTP/1.1
- Один запрос за раз на одно TCP-соединение. Pipelining существует в спецификации, но на практике не работает из-за head-of-line blocking (ответы должны приходить в порядке запросов)
- Для параллельности браузеры открывают 6–8 TCP-соединений к одному серверу
- Заголовки передаются текстом, повторяются в каждом запросе (Cookie, User-Agent — десятки и сотни байт)
- Оптимизации-«костыли»: keep-alive, конкатенация файлов, CSS-спрайты, domain sharding
HTTP/2
- Бинарный протокол — данные передаются в виде фреймов (frames), что эффективнее парсинга текста
- Мультиплексирование — множество запросов и ответов передаются одновременно по одному TCP-соединению, чередуясь фреймами. Не нужно ждать завершения предыдущего запроса
- Сжатие заголовков (HPACK) — заголовки сжимаются и индексируются; повторяющиеся заголовки передаются как ссылки на индекс
- Server Push — сервер может отправить ресурсы до того, как клиент их запросит (например, CSS к HTML-странице)
- Проблема: head-of-line blocking на уровне TCP — если один TCP-пакет потерян, все потоки HTTP/2 ждут его повторной передачи, даже если потеря касается только одного потока
HTTP/3
- Использует QUIC — транспортный протокол поверх UDP, разработанный Google
- Каждый HTTP-поток в QUIC независим: потеря пакета одного потока не блокирует другие — head-of-line blocking полностью решён
- Встроенное шифрование (TLS 1.3) — handshake QUIC и TLS происходят одновременно, что сокращает время установления соединения
- 0-RTT — при повторном подключении к серверу данные могут отправляться сразу, без ожидания handshake
- Миграция соединений — QUIC идентифицирует соединение по Connection ID, а не по IP:port, что позволяет сохранять соединение при смене сети (Wi-Fi → мобильная сеть)
- Лучше работает при нестабильном соединении (мобильные сети, потери пакетов)
Эволюция решения проблемы HOL blocking
Пример
HTTP/1.1: Запрос 1 ──→ Ответ 1 ──→ Запрос 2 ──→ Ответ 2 (последовательно)
HTTP/2: Запрос 1 ─┐ (мультиплекс, но
Запрос 2 ─┤── один TCP-поток ──→ TCP потеря ──→ все ждут)
Запрос 3 ─┘
HTTP/3: Запрос 1 ─── QUIC поток 1 ──→ потеря ──→ ждёт только поток 1
Запрос 2 ─── QUIC поток 2 ──→ OK (независимо)
Запрос 3 ─── QUIC поток 3 ──→ OK (независимо)
Для Java-разработчика
java.net.http.HttpClient(Java 11+) поддерживает HTTP/1.1 и HTTP/2- Spring Boot (Tomcat, Jetty, Netty) поддерживает HTTP/2 с минимальной конфигурацией (
server.http2.enabled=true) - Для HTTP/3 пока нужны сторонние библиотеки или reverse proxy (Nginx 1.25+, Caddy, HAProxy)
- В микросервисной архитектуре HTTP/2 между сервисами (например, gRPC) даёт существенный прирост за счёт мультиплексирования
Вывод
HTTP/1.1 → HTTP/2 → HTTP/3 — это эволюция в сторону более быстрой, параллельной и устойчивой передачи данных. HTTP/2 решил проблему блокировки на уровне HTTP, HTTP/3 — на уровне транспорта. Для большинства Java-приложений HTTP/2 уже доступен из коробки; HTTP/3 приходит через reverse proxy.
На собеседовании: ключевой вопрос — что такое head-of-line blocking и как каждая версия его решает. Также полезно объяснить, почему HTTP/3 использует UDP (не потому что он «быстрее», а потому что TCP нельзя модифицировать в middlebox — маршрутизаторах и NAT — а QUIC реализует надёжность поверх UDP в user space).