33 / 41
Что такое HTTP/2 мультиплексирование?
Полный ответ
Сравнение HTTP/1.1 и HTTP/2:
JavaScript
HTTP/1.1 (6 соединений, запросы последовательны в каждом):
Соединение 1: [--- style.css ---][--- logo.png ---]
Соединение 2: [--- app.js ------][--- font.woff2 -]
Соединение 3: [--- vendor.js ---]
Соединение 4: [--- hero.jpg ----]
Соединение 5: [--- analytics.js ]
Соединение 6: [--- icons.svg ---]
HTTP/2 (1 соединение, всё параллельно через потоки):
Соединение:
Stream 1: [frame][frame] [frame] = style.css
Stream 3: [frame][frame][frame] = app.js
Stream 5: [frame] [frame][frame] = vendor.js
Stream 7: [frame] [frame] [frame] = hero.jpg
Stream 9: [frame][frame] = logo.png
...все чередуются в одном TCP-соединении
Структура HTTP/2:
JavaScript
HTTP/2 соединение
|
|-- Stream 1 (запрос/ответ для style.css)
| |-- HEADERS frame (запрос)
| |-- HEADERS frame (ответ)
| |-- DATA frame (часть тела)
| |-- DATA frame (часть тела)
|
|-- Stream 3 (запрос/ответ для app.js)
| |-- HEADERS frame
| |-- DATA frame
| |-- DATA frame
| |-- DATA frame
|
|-- Stream 5 (запрос/ответ для hero.jpg)
|-- HEADERS frame
|-- DATA frame
|-- ...
Проверка HTTP/2 в браузере:
JavaScript
// Через Resource Timing API
const resources = performance.getEntriesByType('resource');
for (const res of resources) {
console.log(`${res.name}: ${res.nextHopProtocol}`);
// "h2" -- HTTP/2
// "h3" -- HTTP/3
// "http/1.1" -- HTTP/1.1
}
// Проверка для текущей страницы
const [nav] = performance.getEntriesByType('navigation');
console.log(`Страница загружена по: ${nav.nextHopProtocol}`);
Что это значит для разработчика:
JavaScript
// В HTTP/1.1 делали так (domain sharding -- антипаттерн для HTTP/2):
// ❌ Распределяли ресурсы по доменам для обхода лимита соединений
// <img src="https:// img1.example.com/photo1.jpg">
// <img src="https:// img2.example.com/photo2.jpg">
// <img src="https:// img3.example.com/photo3.jpg">
// Каждый домен -- отдельные 6 соединений
// ✅ При HTTP/2 все ресурсы с одного домена -- через один коннект
// <img src="https:// cdn.example.com/photo1.jpg">
// <img src="https:// cdn.example.com/photo2.jpg">
// <img src="https:// cdn.example.com/photo3.jpg">
// Один домен, одно соединение, все параллельно
JavaScript
// HTTP/1.1 антипаттерн: объединение файлов в спрайты и мега-бандлы
// ❌ Раньше: один огромный bundle.js (всё в одном, чтобы один запрос)
// При HTTP/2 это вредит, потому что:
// 1. Изменение одного модуля инвалидирует весь кеш
// 2. Пользователь грузит ненужный код
// ✅ С HTTP/2: гранулярные чанки
// vendor.js, auth.js, dashboard.js, profile.js
// Параллельная загрузка, лучшее кеширование
Настройка HTTP/2 на сервере:
Nginx
# nginx -- HTTP/2 включается одной директивой
server {
listen 443 ssl http2;
# HTTP/2 требует TLS (технически не обязательно, но все браузеры требуют)
ssl_certificate /etc/ssl/cert.pem;
ssl_certificate_key /etc/ssl/key.pem;
# Увеличение лимитов потоков
http2_max_concurrent_streams 128; # по умолчанию 128
}
📌 Реальные кейсы
Влияние мультиплексирования на загрузку:
JavaScript
Страница с 50 ресурсами:
HTTP/1.1 (6 параллельных соединений):
Раунд 1: 6 ресурсов параллельно
Раунд 2: 6 ресурсов параллельно
...
Раунд 9: 2 ресурса (остаток)
Итого: ~9 раундов, каждый ждёт самый медленный ресурс в группе
HTTP/2 (1 соединение, все параллельно):
Все 50 запросов отправлены одновременно
Ответы приходят по мере готовности
Нет блокировки одного запроса другим (на уровне HTTP)
Итого: общее время определяется самым медленным ресурсом
Когда мультиплексирование не помогает:
JavaScript
1. Если сервер отдаёт ресурсы последовательно (однопоточный бэкенд)
2. Если TCP-окно слишком маленькое (slow start на новом соединении)
3. При потере TCP-пакета ВСЕ потоки блокируются (TCP Head-of-Line Blocking)
Эту проблему решает HTTP/3 (QUIC поверх UDP)
Резюме
Мультиплексирование -- главное улучшение HTTP/2. Одно TCP-соединение вместо 6-8, все запросы параллельно, нет очередей. Это делает бессмысленными хаки вроде domain sharding и CSS-спрайтов. Но TCP Head-of-Line Blocking остаётся проблемой -- её решает HTTP/3 (QUIC).