← Назад к вопросам

Как решали проблемы с multiplexing в HTTP/1?

1.3 Junior🔥 131 комментариев
#Браузер и сетевые технологии

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как решали проблемы с multiplexing в HTTP/1?

В HTTP/1 существовала критическая проблема с multiplexing — браузер не мог одновременно загружать несколько ресурсов по одному соединению. Каждый запрос ждал, пока завершится предыдущий. Это создавало серьёзные проблемы производительности.

Проблема: Head-of-Line Blocking

В HTTP/1 за одно TCP соединение можно было отправить только один запрос и дождаться ответа:

Браузер                     Сервер
   |
   |---GET /index.html--->
   |                         |
   |<---200 index.html----
   |                         (ждёт завершения)
   |---GET /style.css----->
   |                         |
   |<---200 style.css----
   |                         (ждёт завершения)
   |---GET /script.js----->
   |                         |
   |<---200 script.js----

Все запросы выстраивались в очередь. Если один запрос был медленным, он блокировал все остальные (Head-of-Line Blocking).

Решение 1: Keep-Alive соединения

Вместо закрытия соединения после каждого ответа, браузер оставляет его открытым для повторного использования:

HTTP/1.0 (без Keep-Alive):
- Соединение открывается
- Запрос + ответ
- Соединение закрывается (overhead!)

HTTP/1.1 с Keep-Alive (Connection: keep-alive):
- Соединение открывается один раз
- Множество запросов + ответов
- Соединение закрывается в конце

Это снижает overhead открытия TCP соединения, но не решает главную проблему — ждать ответ перед следующим запросом.

Решение 2: Pipelining (редко использовалось)

HTTP Pipelining позволял отправить несколько запросов без ожидания ответа:

Браузер                     Сервер
   |
   |---GET /index.html--->
   |---GET /style.css----->
   |---GET /script.js----->
   |                         (обрабатывает все)
   |<---200 index.html----
   |<---200 style.css----
   |<---200 script.js----

Но были проблемы:

  • Многие прокси и серверы не поддерживали правильно
  • Если один ответ не пришёл, остальные ждут (всё ещё HOL blocking)
  • Непредсказуемое поведение
  • Был отключен в большинстве браузеров

Решение 3: Множественные TCP соединения

Так как HTTP/1 не позволял мультиплексировать в одном соединении, браузеры открывали несколько параллельных соединений:

// Браузеры современные открывают 6-8 соединений одновременно
Browser HTTP/1 Connection Limit: {
  Firefox:  6 соединений per domain
  Chrome:   6 соединений per domain
  Safari:   6 соединений per domain
}

Визуально:

Соединение 1:  index.html ---->
                              <--- ответ

Соединение 2:  style.css  ---->
                              <--- ответ

Соединение 3:  script.js  ---->
                              <--- ответ

Соединение 4:  image.png  ---->
                              <--- ответ

Это значительно улучшило скорость, но было расточительным (много TCP handshake, больше памяти).

Решение 4: Domain Sharding (хак)

Разработчики создавали несколько доменов для одного сайта, чтобы получить больше соединений:

<!-- Старый трюк -->
<img src="https://images1.example.com/pic.jpg">
<img src="https://images2.example.com/pic2.jpg">
<img src="https://images3.example.com/pic3.jpg">

<!-- Каждый домен получает свой лимит соединений! -->

Это был обходной путь, но неэлегантный.

Решение 5: Sprite sheets и объединение файлов

Разработчики объединяли множество изображений в один (sprite sheet) и объединяли CSS файлы:

/* Вместо 10 отдельных запросов для 10 иконок */
background-image: url('sprite.png');
background-position: -0px -0px;  /* icon 1 */
background-position: -32px -0px; /* icon 2 */

Это работало, но усложняло разработку и кэширование.

Решение 6: Inline ресурсы (Data URI)

<img src="data:image/png;base64,iVBORw0KGgo...">
<style>
  body { background: url('data:image/svg+xml;utf8,...'); }
</style>

Помещение картинок прямо в HTML/CSS избегало дополнительных запросов. Минус: большие файлы, плохой кэширование.

HTTP/2 решил проблему (2015)

HTTP/2 наконец добавил истинный multiplexing в одном соединении:

Одно TCP соединение:
   |
   |---[Stream 1: index.html]--->
   |---[Stream 2: style.css]--->
   |---[Stream 3: script.js]--->
   |                              (все параллельно)
   |<---[Stream 1 response]----
   |<---[Stream 2 response]----
   |<---[Stream 3 response]----

Всё работает параллельно в одном соединении без HOL blocking.

Резюме

  • HTTP/1 не мог загружать несколько ресурсов одновременно
  • Keep-Alive — переиспользование соединения
  • Pipelining — попытка отправить несколько запросов (не работало в реальности)
  • Множественные соединения — открыть 6-8 одновременно (большой overhead)
  • Domain Sharding — трюк с несколькими доменами (некрасиво)
  • Объединение файлов — sprite sheets, минификация (усложняет разработку)
  • Inline ресурсы — Data URIs (плохой кэширование)
  • HTTP/2 (2015) решил это стандартизированным multiplexing'ом
  • Сегодня используется HTTP/2 или HTTP/3, и старые трюки больше не нужны