Что означает мультиплексирование в HTTP/2
Может ли кто-нибудь объяснить, что такое мультиплексирование по отношению к HTTP/2 и как оно работает?
3 ответа
Проще говоря, мультиплексирование позволяет вашему браузеру запускать несколько запросов одновременно для одного и того же соединения и получать запросы обратно в любом порядке.
А теперь за гораздо более сложный ответ...
Когда вы загружаете веб-страницу, она загружает HTML-страницу, видит, что ей нужно немного CSS, немного JavaScript, загрузка изображений... и т. Д.
Под HTTP/1.1 вы можете загружать только один из них за раз по соединению HTTP/1.1. Таким образом, ваш браузер загружает HTML, а затем запрашивает файл CSS. Когда он возвращается, он запрашивает файл JavaScript. Когда он возвращается, он запрашивает первый файл изображения... и т. Д. HTTP/1.1 в основном синхронный - когда вы отправляете запрос, вы застреваете, пока не получите ответ. Это означает, что большую часть времени браузер делает не очень много, так как он запускает запрос, ждет ответа, затем запускает другой запрос, затем ждет ответа... и т. Д. Конечно, сложные сайты с Для большого количества JavaScript требуется, чтобы браузер выполнял большую обработку, но это зависит от загружаемого JavaScript, поэтому, по крайней мере, для начала задержки, наследуемые для HTTP/1.1, вызывают проблемы. Обычно сервер тоже не очень много работает (по крайней мере, по запросу - конечно, они складываются для занятых сайтов), потому что он должен почти мгновенно отвечать за статические ресурсы (такие как CSS, JavaScript, изображения, шрифты и т. Д.) и, надеюсь, не слишком долго, даже для динамических запросов (которые требуют вызова базы данных или тому подобное).
Таким образом, одной из основных проблем в сети сегодня является задержка в сети при отправке запросов между браузером и сервером. Это может быть только десятки или, возможно, сотни миллисекунд, что может показаться небольшим, но они складываются и часто являются самой медленной частью просмотра веб-страниц - особенно когда веб-сайты становятся все более сложными и требуют дополнительных ресурсов (по мере их поступления) и доступа в Интернет. все чаще через мобильный телефон (с более медленной задержкой, чем широкополосный).
В качестве примера, скажем, есть 10 ресурсов, которые ваша веб-страница должна загрузить после загрузки самого HTML (это очень маленький сайт по сегодняшним стандартам, так как более 100 ресурсов распространено, но мы будем простыми и продолжим с этим пример). И скажем, каждый запрос занимает 100 мс для прохождения через Интернет к веб-серверу и обратно, а время обработки на обоих концах незначительно (скажем, 0 для этого примера для простоты). Поскольку вы должны отправлять каждый ресурс и ждать ответа по одному, для загрузки всего сайта потребуется 10 * 100 мс = 1000 мс или 1 секунда.
Чтобы обойти это, браузеры обычно открывают несколько подключений к веб-серверу (обычно 6). Это означает, что браузер может запускать несколько запросов одновременно, что намного лучше, но за счет сложности, связанной с настройкой и управлением несколькими соединениями (что влияет как на браузер, так и на сервер). Давайте продолжим предыдущий пример и также скажем, что есть 4 соединения и, для простоты, скажем, все запросы равны. В этом случае вы можете разделить запросы по всем четырем соединениям, так что два будут иметь 3 ресурса для получения, а два будут иметь 2 ресурса, чтобы полностью получить десять ресурсов (3 + 3 + 2 + 2 = 10). В этом случае наихудший случай - 3 раунда или 300 мс = 0,3 секунды - хорошее улучшение, но этот простой пример не включает в себя стоимость установки этих нескольких соединений, а также нехватку ресурсов для управления ими (чего я еще не делал) здесь, поскольку этот ответ уже достаточно длинный, но для настройки отдельных TCP-соединений требуются время и другие ресурсы - чтобы выполнить TCP-соединение, HTTPS-рукопожатие и затем набрать полную скорость из-за медленного запуска TCP).
HTTP/2 позволяет отправлять несколько запросов по одному и тому же соединению, поэтому вам не нужно открывать несколько соединений, как указано выше. Так что ваш браузер может сказать: "Дай мне этот файл CSS. Дай мне этот файл JavaScript. Дай мне изображение1.jpg. Дай мне изображение2.jpg... и т. Д." полностью использовать одно соединение. Это имеет очевидное преимущество в производительности, поскольку не откладывает отправку запросов, ожидающих свободного соединения. Все эти запросы проходят через Интернет к серверу параллельно. Сервер отвечает каждому, и затем они начинают возвращаться. На самом деле это даже более мощно, чем то, что веб-сервер может реагировать на них в любом порядке и отправлять файлы в другом порядке, или даже разбивать каждый запрошенный файл на части и смешивать файлы вместе. Это имеет вторичное преимущество: один тяжелый запрос не блокирует все остальные последующие запросы (известный как проблема блокировки заголовка строки). Веб-браузер затем ставит задачу собрать все части вместе. В лучшем случае (при условии отсутствия ограничений полосы пропускания - см. Ниже), если все 10 запросов выполняются практически одновременно одновременно и сразу же отвечают сервером, это означает, что у вас, по сути, есть один прием в оба конца или 100 мс или 0,1 секунды, чтобы скачать все 10 ресурсов. И это не имеет недостатков, которые были у нескольких соединений для HTTP/1.1! Это также гораздо более масштабируемо по мере роста ресурсов на каждом веб-сайте (в настоящее время браузеры открывают до 6 параллельных подключений в HTTP/1.1, но разве они должны расти по мере усложнения сайтов?).
Эта диаграмма показывает различия, и есть анимированная версия тоже.
Примечание: HTTP/1.1 имеет концепцию конвейерной передачи, которая также позволяет отправлять несколько запросов одновременно. Однако их по-прежнему нужно было возвращать в полном порядке, чтобы их запрашивали, так что это далеко не так хорошо, как HTTP/2, даже если концептуально это похоже. Не говоря уже о том, что он настолько плохо поддерживается как браузерами, так и серверами, поэтому редко используется.
В комментариях ниже подчеркивается, как пропускная способность влияет на нас. Конечно, ваше интернет-соединение ограничено тем, сколько вы можете загрузить, а HTTP/2 не учитывает это. Таким образом, если все эти 10 ресурсов, рассмотренные в приведенных выше примерах, являются массивными изображениями с качеством печати, их загрузка все равно будет медленной. Однако для большинства веб-браузеров пропускная способность является меньшей проблемой, чем задержка. Поэтому, если эти десять ресурсов представляют собой небольшие элементы (в частности, текстовые ресурсы, такие как CSS и JavaScript, которые могут быть сжаты, чтобы быть крошечными), как это часто бывает на веб-сайтах, то пропускная способность на самом деле не является проблемой - проблема заключается в большом количестве ресурсов. и HTTP/2 ищет решение этой проблемы. Вот почему конкатенация используется в HTTP/1.1 в качестве другого обходного пути, поэтому, например, все CSS часто объединяются в один файл: количество загружаемых CSS одинаково, но при использовании этого ресурса в качестве одного ресурса можно получить огромные преимущества в производительности (хотя с HTTP/2 - меньше, и на самом деле некоторые говорят, что конкатенация должна быть анти-паттерном в HTTP/2 - хотя есть и аргументы против полного отказа от него).
Для примера: предположим, что вам нужно заказать 10 предметов из магазина для доставки на дом:
HTTP/1.1 с одним соединением означает, что вы должны заказывать их по одному, и вы не можете заказать следующий товар, пока не прибудет последний. Вы можете понять, что потребуются недели, чтобы пройти через все.
HTTP/1.1 с несколькими подключениями означает, что вы можете иметь (ограниченное) количество независимых заказов на ходу одновременно.
HTTP/1.1 с конвейерной передачей означает, что вы можете запрашивать все 10 элементов один за другим, не ожидая, но затем все они приходят в том порядке, в котором вы их запрашивали. И если одного товара нет в наличии, вам придется подождать, прежде чем вы получите товары, которые вы заказали после этого - даже если эти более поздние товары действительно есть в наличии! Это немного лучше, но все еще подвержены задержкам, и, скажем, большинство магазинов все равно не поддерживают этот способ заказа.
HTTP/2 означает, что вы можете заказать свои товары в любом конкретном порядке - без каких-либо задержек (аналогично приведенному выше). Магазин отправит их, когда они будут готовы, поэтому они могут прийти в другом порядке, чем вы их просили, и они могут даже разделить предметы, так что некоторые части этого заказа прибывают первыми (так лучше, чем выше). В конечном итоге это должно означать, что вы 1) в целом получите все быстрее и 2) сможете начать работать с каждым элементом по мере его поступления ("о, это не так хорошо, как я думал, поэтому я мог бы заказать что-то еще или вместо")).
Конечно, вы по-прежнему ограничены размером своего фургона почтальона (пропускной способностью), поэтому им, возможно, придется оставить некоторые пакеты обратно в сортировочный офис до следующего дня, если они заполнены на этот день, но это редко проблема по сравнению с задержкой в фактической отправке заказа через и обратно. Большая часть просмотра веб-страниц включает отправку маленьких писем назад и вперед, а не громоздкие посылки.
Надеюсь, это поможет.
Поскольку ответ @Juanma Menendez правильный, а его диаграмма сбивает с толку, я решил улучшить его, прояснив разницу между мультиплексированием и конвейерной обработкой, понятиями, которые часто смешивают.
Конвейерная обработка (HTTP/1.1)
Несколько запросов отправляются через одно и то же HTTP-соединение. Ответы приходят в том же порядке. Если первый ответ занимает много времени, другие ответы должны ждать в очереди. Подобно конвейерной передаче ЦП, когда одна инструкция выбирается, пока другая декодируется. Одновременно выполняется несколько инструкций, но их порядок сохраняется.
Мультиплексирование (HTTP/2)
Несколько запросов отправляются через одно и то же HTTP-соединение. Ответы принимаются в произвольном порядке. Не нужно ждать медленного ответа, который блокирует других. Подобно выполнению инструкций вне очереди в современных процессорах.
Надеюсь, улучшенное изображение проясняет разницу:
Запросить мультиплексирование
HTTP/2 может отправлять несколько запросов данных параллельно через одно TCP-соединение. Это наиболее продвинутая функция протокола HTTP/2, поскольку она позволяет загружать веб-файлы асинхронно с одного сервера. Большинство современных браузеров ограничивают TCP-соединения одним сервером. Это сокращает дополнительное время приема-передачи (RTT), ускоряет загрузку вашего веб-сайта без какой-либо оптимизации и делает ненужным сегментирование домена.
Мультиплексирование в HTTP 2.0 - это тип отношений между браузером и сервером, которые используют одно соединение для параллельной доставки нескольких запросов и ответов, создавая множество отдельных фреймов в этом процессе.
Мультиплексирование нарушает строгую семантику запрос-ответ и позволяет устанавливать отношения один-ко-многим или многие-ко-многим.
Простой ответ ( источник):
Мультиплексирование означает, что ваш браузер может отправлять несколько запросов и получать несколько "упакованных" ответов в одно TCP-соединение. Таким образом, рабочая нагрузка, связанная с поиском DNS и рукопожатиями, сохраняется для файлов, поступающих с одного сервера.
Сложный / Детальный ответ:
Посмотрите ответ, предоставленный @BazzaDP.
Мультиплексирование HTTP/2 подразумевает отсутствие больших или медленных ресурсов, задерживающих доставку меньших или более быстрых ресурсов, а также отсутствие необходимости нескольких соединений (и сопутствующих им сложностей и накладных расходов) для загрузки нескольких ресурсов.
Допустим, у вас есть шахта, и вы добываете из нее различные виды руды. У вас есть одна конвейерная лента с такими ковшами:
(но действительно большой). Каждое ведро на конвейере может вместить 1 кубический метр (1 м³) руды (назовем это посылкой), и конвейер доставляет 1 ведро в минуту. Таким образом, в теории, чтобы извлечь 10 пакетов руды, требуется 10 ведер, и так 10 минут. Но средний майнер не может загружать ленту так быстро, как он движется, он может загружать только половину каждого ковша, поэтому, когда один средний майнер загружает конвейер, он не используется полностью; 10 пакетов руды занимают 20 наполовину заполненных ведер и занимают 20 минут. Только супер-майнер может полностью загрузить ведро.
Когда вы звоните вниз, чтобы сказать, какой груз загружать следующим, майнер должен отправить записку, в которой говорится, что идет (в одном ведре), и оставить следующие два ведра пустыми, чтобы люди наверху могли переместить нужные контейнеры в нужное положение.
Вы, вероятно, уже подозревали, что:
- Ленточный конвейер - это ваше сетевое соединение, его скорость - ваша пропускная способность.
- Записка и пустые корзины - это стоимость задержки. (Это не очень хорошая аналогия с задержкой, но фундаментальный момент заключается в том, что запрос ресурса стоит).
Скажем, мы начинаем с трех майнеров:
- Джек должен доставить 2 посылки с серебряной рудой
- У Джона есть 10 посылок, которые он должен очистить
- Стиву нужно доставить 1 посылку серебряной руды
... а затем в какой-то момент, когда они на полпути через свои поставки, появляются еще два майнера:
- У Кевина есть 6 посылок, которые он должен очистить
- Шейла должна доставить 1 посылку с золотой рудой
(Да, это очень нереальная шахта. Но выгодно.)
У рудника у вас есть много людей и грузовиков, чтобы унести руду и извлечь из нее серебро, золото и железо (и взять добычу для использования на дорожных работах). Чем раньше вы получите товар, тем быстрее вы сможете его продать, и вы действительно захотите продать его как можно быстрее, прежде чем покупатели отправятся куда-то еще.
Одно соединение HTTP/1.x
Только один майнер может загрузить одновременно. Джек подходит, отправляет свою записку в одном ведре и оставляет следующие 2 пустыми, затем начинает загружать свои 2 пакета серебряной руды на конвейер. Поскольку Джек - средний майнер, он может загружать только половину ведра, когда проходит конвейер, поэтому его 2 посылки берут 4 ведра. Таким образом, это было 3 ведра накладных расходов ("Я загружаю серебро") и 4 ведра руды. 7 ведер по 1 ведру в минуту = 7 минут.
Затем Джон подходит, отправляет записку и оставляет следующие 2 ведра пустыми. Джон - супер-шахтер (его полное имя - Джон Генри), поэтому он может полностью загрузить каждое ведро, и поэтому его 10 партий руды берут 10 ведер. Так что это было 3 ведра сверху и 10 ведер руды; 13 минут
Тем временем появляется Кевин и Шейла; но они должны ждать. Это строгая система очередей (мы британцы), поэтому Кевин будет следующим в очереди.
Наконец настала очередь Стива, потом Кевина, а затем Шейлы.
Итак, вот ведра, которые пошли на конвейер
[Записка Джека] [пусто] [пусто] [половинная загрузка с серебряной рудой] [половинная загрузка с серебряной рудой] [половинная загрузка с серебряной рудой] [половинная загрузка с серебряной рудой] [Примечание Джона] [пусто] [пусто] [полностью загружен / испортить] [полностью загружен / испортить] [полностью загружен / испортить] [полностью загружен / испортить] [полностью загружен / испортить] [полностью загружен / испортить] [полностью загружен / испортить] [полностью загружен / испортить] [полностью загружен / испортить] [полностью загружен / испортить] [Примечание Стива] [пусто] [пусто] [половинная загрузка с серебряной рудой] [половинная загрузка с серебряной рудой] [Примечание Кевинса] [пусто] [пусто] [наполовину загружен / испортить] [наполовину загружен / испортить] [наполовину загружен / испортить] [наполовину загружен / испортить] [наполовину загружен / испортить] [наполовину загружен / испортить] [наполовину загружен / испортить] [наполовину загружен / испортить] [наполовину загружен / испортить] [наполовину загружен / испортить] [наполовину загружен / испортить] [наполовину загружен / испортить] [Примечание Шейлы] [пусто] [пусто] [наполовину загруженный с золотой рудой] [наполовину загруженный с золотой рудой]
Всего было использовано 45 ведер, многие из них пустые или полупустые. Потребовалось 45 минут, чтобы получить золотую руду Шейлы, потому что она застряла за добычей Джона и Кевина. Тем временем, покупатель золота устал смотреть, как добыча добывается, и отправился в другую шахту.
Это одно соединение HTTP/1.x. Браузер (вы у рудника) может одновременно получать только один ресурс. Сервер (майнеры) может доставлять медленный ресурс (средний майнер) и / или может иметь дело с большим ресурсом (10 порций Джона испортили). Запрос следующего ресурса требует времени (задержки).
В HTTP/1.x есть что-то, называемое конвейерной обработкой, чтобы уменьшить задержку, но есть проблемы с его развертыванием, и это не мешает огромному грузу Джона или Кевина мешать загрузке золотой руды Шейлой.
Несколько соединений HTTP/1.x
Фирма конвейерных лент предлагает вам модернизацию: они могут установить более новую модель с ковшами, разделенными пополам, и местом для загрузки двух шахтеров в нижней части, каждый в свою половину ковша. Пояс все еще может нести столько же руды, но по крайней мере теперь у вас есть два "канала", так что даже пара средних майнеров может держать его полностью загруженным. Вверху каждая половина ведра доставляется на разные выходы.
Итак, давайте посмотрим на тех же майнеров и нагрузок:
- Джек должен доставить 2 посылки с серебряной рудой
- У Джона есть 10 посылок, которые он должен очистить
- Стиву нужно доставить 1 посылку серебряной руды
затем через некоторое время:
- У Кевина есть 6 посылок, которые он должен очистить
- Шейла имеет 1 посылку с золотой рудой для доставки
Джек и Джон оба подходят, отправляют свои заметки в половинки ведер и оставляют следующие 2 пустыми. Затем Джек использует 4 половинки ведра, чтобы доставить свои 2 посылки серебряной руды, в то время как Джон использует 4 половинки ведра, чтобы доставить 2 из своих 10 пакетов добычи. Джек выходит из пути, Стив подходит, отправляет свою записку, оставляет пустые ведра и доставляет свою руду, в то время как Джон продолжает доставлять свою добычу.
Пока Стив и Джон загружаются, появляется Кевин, затем Шейла и они стоят в очереди. Когда Стив готов, Кевин принимает эту сторону, а когда Джон готов, Шейла принимает эту сторону.
Таким образом, мы получаем эти ведра, каждый из которых делится пополам:
[Записка Джека | Записка Джона] [пусто | пусто] [пусто | пусто] [серебряная руда | портить] [серебряная руда | портить] [серебряная руда | портить] [серебряная руда | испортить] [записка Стива | испортить] [пусто | испортить] [пусто | портить] [серебряная руда | портить] [серебряная руда | испортить] [записка Кевинса | испортить] [пусто | испортить] [пусто | испортить] [испортить | испортить] [испортить | испортить] [испортить | испортить] [испортить | испортить] [испортить | испортить] [испортить | испортить] [испортить | испортить] [испортить | испортить] [испортить | Записка Шейлы] [испортить | пусто] [испортить | пусто] [испортить | золотая руда] [пусто | Золотая руда ]
28 ведер вместо 45, и золотая руда Шейлы прибыла раньше, но все еще удерживалась добычей Джона и Кевина. Лучше 28 минут, но покупатель золота все же устал ждать и ушел.
Это два HTTP/1.x соединения, каждое из которых может доставлять один ресурс. Если веб-страница имеет несколько ресурсов, браузеры обычно открывают как минимум два соединения (иногда до 6 или 8 для настольных браузеров), чтобы они могли загружать вещи параллельно. Это сложно и требует больше ресурсов на сервере, так как ему приходится управлять большим количеством соединений, но по крайней мере он доставляет золотую руду раньше.
HTTP/2 мультиплексирование
Фирма конвейерных лент имеет более новую модернизацию: столько загрузочных станций внизу, сколько вы хотите, где каждое ведро может быть помечено тем, что в нем есть, и все они доставляются на конвейер, где их можно выгружать в соответствии с метки на ведрах. Хорошо, если ведра перемешаны, они разбираются сверху. Все еще требуется одно ведро, чтобы сказать, что будет, но вам больше не нужно оставлять пустые ведра. И каждое ведро может быть отправлено, когда оно будет готово, так что средние майнеры не тратят пространство конвейера с полупустыми ведрами, так как они просто заполняют свое ведро, а затем вставляют его, когда другие ведра выходят.
Итак, давайте посмотрим на наших трудолюбивых майнеров:
- Джек должен доставить 2 посылки с серебряной рудой
- У Джона есть 10 посылок, которые он должен очистить
- Стиву нужно доставить 1 посылку серебряной руды
затем через некоторое время:
- У Кевина есть 6 посылок, которые он должен очистить
- Шейла должна доставить 1 посылку с золотой рудой
Поскольку сегменты могут быть смешаны, и нам больше не нужны пустые сегменты, мы получаем что-то вроде этого (каждая строка представляет собой полный блок):
[Записка Джека] [записка Джона] [записка Стива] [серебряная руда Джека] [добыча Джона] [серебряная руда Стива] [добыча Джона] [серебряная руда Джека] [добыча Джона] [добыча Джона] [добыча Джона] [записка Кевина ] Это когда появляется Кевин... [записка Шейлы] ... и затем Шейла вскоре после [добычи Джона] [добычи Кевина] [золотой руды Шейлы] [добычи Джона] [добычи Кевина] [добычи Джона] [добычи Кевина ] [Портить Джона] [портить Кевина] [портить Джона] [портить Кевина] [портить Кевина]
25 ведер, 5 с нотами и 20 полностью загруженных рудой. 25 минут Сокращение с 28 в основном из-за улучшения системы мечения (больше нет пустых корзин). Мы не могли сделать конвейерную ленту быстрее, мы просто использовали ее более эффективно.
Но! Обратите внимание, что золотая руда Шейлы больше не задерживалась добычей Джона и Кевина, она просто перемешивалась (мультиплексировалась) с потоком ведер, идущих к руднику, когда он был готов (когда Шейла появилась). Так что его доставили через 16 минут вместо 28 или 45. Покупатель все еще был там. Прибыль!
Это HTTP/2 мультиплексирование. Одно соединение, несколько запросов, смешанные ответы.
Случилось так, что, когда нужно было отправить только один ресурс (как раз перед тем, как появились Кевин и Шейла, когда Джон все еще загружал добычу, и он был единственным, кто что-то делал), это делал наш супер-майнер Джон, поэтому у нас не было полупустых ведер. Если бы я начинал этот ответ с нуля, я бы настроил его так, чтобы вместо него был Джек, и у нас было несколько полупустых ведер, потому что мы могли бы иметь, HTTP/2 не может волшебным образом сделать медленный ресурс (Джек загружает свой серебряная руда) быстрее, поэтому, если бы Джек работал один, у нас были бы полупустые ведра. (Я также настроил бы его так, чтобы обычный майнер мог полностью загружать корзины и просто замедлять работу Джека, поскольку медленные ресурсы, вероятно, не являются нормой.)
Подробнее: Часто задаваемые вопросы по HTTP/2.