HTTP / 2 делает веб-сокеты устаревшими?

268

Я изучаю протокол HTTP / 2. Это двоичный протокол с небольшими фреймами сообщений. Это позволяет мультиплексировать поток через одно соединение TCP. Концептуально это выглядит очень похоже на WebSockets.

Планируется ли устаревание веб-сокетов и их замена какими-либо HTTP / 2-запросами без заголовков и push-сообщениями, инициируемыми сервером? Или WebSockets дополнит HTTP / 2?

vbezhenar
источник
Я думаю, что принятый ответ является правильным, веб-сокеты все еще являются предпочтительным решением для веб-приложений для двунаправленной связи с сервером, включая сообщения, отправляемые сервером. HTTP используется не только для браузеров, и когда и клиент, и сервер могут использовать низкоуровневый API, им не нужны веб-сокеты. Тем не менее, большинство людей используют HTTP для веб-приложений и в основном озабочены API, доступными для JavaScript. Если модераторы считают, что принятый ответ должен быть другим, я не против этого, поскольку этот вопрос, по-видимому, вызывает много мнений, и мое мнение может быть ошибочным.
вбеженар

Ответы:

162

Из того, что я понял, HTTP / 2 не является заменой веб-сокета, но стремится стандартизировать протокол SPDY.

В HTTP / 2 server-push используется за сценой для улучшения загрузки ресурсов клиентом из браузера. Как разработчик, вы не заботитесь об этом во время разработки. Тем не менее, с Websocket, разработчик может использовать API, который может использовать и отправлять сообщения с уникальным полнодуплексным соединением.

Это не одно и то же, и они должны дополнять друг друга.

Гийом Д.
источник
3
Спасибо, Гийом, за ваш ответ. Однако мне интересно, можете ли вы (или кто-то другой) добавить ссылку из спецификации HTTP / 2. Что я прочитал из блогов и так далее - с HTTP / 2 происходит истинное двунаправленное общение?
Мартин Мизер
3
Не уверен, что спецификация HTTP / 2 - это то место, где можно подробно рассказать о происхождении HTTP / 2 и о том, чем он отличается от веб-сокета. Однако вы можете легко увидеть, что с HTTP / 2 мы используем двунаправленную связь: goo.gl/IJVxWS (стр. 6 и 13)
Гийом Д.
27
HTTP / 2 действительно является двунаправленным, но не симметричным, это означает, что только клиент может отправлять правильный запрос, а сервер может отправлять ответы и запрашивать обещания (push). Это делает веб-сокеты разными в том смысле, что обе стороны более «равны» с точки зрения того, что им разрешено отправлять / получать.
Джордж Антониадис
3
На радио IEEE Software Engineering Radio есть отличный подкаст о происхождении HTTP2. Я думаю, что это так: se-radio.net/2015/07/episode-232-mark-nottingham-on-http2
Макс Мерфи,
2
аналогичный ответ с полным обоснованием можно найти в этой статье InfoQ
mantrid
153

После того, как я закончил читать спецификацию HTTP / 2 , я думаю, что HTTP / 2 делает устаревшие веб-сокеты для большинства случаев использования, но, возможно, не для всех.

PUSH_PROMISE(в разговорной речи известный как серверный пуш) здесь не проблема. Это просто оптимизация производительности.

Основным вариантом использования веб-сокетов в браузере является включение двунаправленной потоковой передачи данных. Итак, я думаю, что вопрос OP заключается в том, выполняет ли HTTP / 2 лучшую работу по включению двунаправленной потоковой передачи в браузере, и я думаю, что да, это так.

Прежде всего, это является би-ди. Просто прочитайте введение в раздел потоков :

«Поток» - это независимая двунаправленная последовательность кадров, которыми обмениваются клиент и сервер в рамках соединения HTTP / 2. Потоки имеют несколько важных характеристик:

Одно соединение HTTP / 2 может содержать несколько одновременно открытых потоков, причем чередование конечных точек чередует кадры из нескольких потоков.

Потоки могут устанавливаться и использоваться в одностороннем порядке или совместно использоваться клиентом или сервером.

Потоки могут быть закрыты любой конечной точкой.

Статьи как это (связанные в другой ответ) не правы об этом аспекте HTTP / 2. Говорят, это не биди. Посмотрите, есть одна вещь, которая не может произойти с HTTP / 2: после открытия соединения сервер не может инициировать обычный поток, только push-поток. Но как только клиент открывает поток, отправляя запрос, обе стороны могут в любое время отправлять кадры DATA через постоянный сокет - полный биди.

Это не сильно отличается от веб-сокетов: клиент должен инициировать запрос на обновление веб-сокета, прежде чем сервер также сможет отправлять данные.

Самое большое отличие состоит в том, что, в отличие от веб-сокетов, HTTP / 2 определяет свою семантику мультиплексирования: как потоки получают идентификаторы и как кадры переносят идентификатор потока, в котором они находятся. HTTP / 2 также определяет семантику управления потоками для определения приоритетов потоков. Это важно в большинстве реальных приложений биди.

(Эта неправильная статья также говорит о том, что стандарт Websocket имеет мультиплексирование. Нет, это не так. Найти его совсем не сложно, просто откройте Websocket RFC 6455 и нажмите ⌘-F и введите «мультиплекс». После прочтения

Протокол предназначен для расширения; будущие версии, вероятно, будут вводить дополнительные понятия, такие как мультиплексирование.

Вы обнаружите, что существует черновое расширение 2013 года для мультиплексирования Websocket. Но я не знаю, какие браузеры, если таковые имеются, поддерживают это. Я не стал бы пытаться создать свое SPA-приложение на обратной стороне этого расширения, особенно с приходом HTTP / 2, поддержка может и не прийти).

Мультиплексирование - это именно то, что вам обычно приходится делать каждый раз, когда вы открываете веб-сокет для биди, скажем, для питания реактивно обновляемого одностраничного приложения. Я рад, что это в спецификации HTTP / 2, позаботился раз и навсегда.

Если вы хотите знать, что может сделать HTTP / 2, просто посмотрите на gRPC. gRPC реализован через HTTP / 2. Обратите особое внимание на варианты потоковой передачи в полудуплексном и полнодуплексном режиме, которые предлагает gRPC. (Обратите внимание, что gRPC в настоящее время не работает в браузерах, но это на самом деле потому, что браузеры (1) не предоставляют фрейм HTTP / 2 клиентскому javascript, и (2) обычно не поддерживают трейлеры, которые используются в спецификация gRPC)

Где еще могут быть веб-розетки? Большим из них является бинарные данные, передаваемые через сервер -> браузер. HTTP / 2 разрешает двоичные данные, передаваемые сервером-> браузером, но не отображается в браузере JS. Для таких приложений, как передача аудио и видео кадров, это причина использовать веб-сокеты.

Изменить: 17 января 2020

Со временем этот ответ постепенно поднялся до вершины (что хорошо, потому что этот ответ более или менее правильный). Тем не менее, по-прежнему время от времени появляются комментарии о том, что это неверно по разным причинам, обычно связанным с некоторой путаницей PUSH_PROMISEили тем, как на самом деле использовать ориентированный на сообщения сервер -> клиентский толчок в одностраничном приложении. И есть вариант использования для веб-сокетов в браузере, который представляет собой двоичные данные, передаваемые сервером. Для текстовых данных, включая JSON, не используйте веб-сокеты, используйте SSE.

Напомним: протокол HTTP / 2 полон би-ди. Тем не менее, современные веб-браузеры не предоставляют JavaScript / Frame-ориентированный протокол HTTP / 2 . Тем не менее, если вы делаете несколько запросов к одному и тому же источнику через соединение HTTP / 2, весь этот трафик мультиплексируется в одном соединении (и это то, что нас волнует!).

Поэтому, если вам нужно создать приложение для чата в реальном времени, скажем, где вам нужно транслировать новые сообщения чата всем клиентам в комнате чата, которые имеют открытые соединения, вы можете (и, вероятно, должны) сделать это без веб-сокетов.

Вы должны использовать события, отправленные сервером, для отправки сообщений вниз и API Fetch для отправки запросов вверх. Server-Sent Events (SSE) - это малоизвестный, но хорошо поддерживаемый API, который предоставляет ориентированный на сообщения поток сервер-клиент. Хотя это не похоже на клиентский JavaScript, внутри вашего браузера (если он поддерживает HTTP / 2) будет повторно использоваться одно TCP-соединение для мультиплексирования всех этих сообщений. Там нет потери эффективности и на самом деле это выигрыш над веб-сокетами. Нужно несколько потоков? Откройте несколько источников событий! Они будут автоматически мультиплексированы для вас.

Помимо более эффективного использования ресурсов и меньшей начальной задержки, чем при рукопожатии через веб-сокет, Server-Sent Events обладают замечательным свойством, заключающимся в том, что они автоматически отступают и работают через HTTP / 1.1. Но когда у вас есть соединение HTTP / 2, они работают невероятно хорошо.

Вот хорошая статья с реальным примером выполнения SPA с реактивно-обновляемым обновлением.

masonk
источник
21
Этот ответ частично не согласен с другими, в том числе принятым, и это также лучший ответ, потому что он основан на прямых источниках.
Судо
7
Я полностью согласен с этим ответом и комментарием. HTTP / 2 является двунаправленным потоком.
Мартин Мизер
3
Собственно правильный ответ, парню надоело проверять источники и приложения реального мира (grpc)
Владимир Акопян
1
В веб-сокетах сервер не может начать выдвигать произвольные байты, пока клиент не инициирует запрос на обновление веб-сокета, но затем он может выполнить запрос в любое время. В HTTP / 2 сервер не может начать передачу байтов, пока клиент не инициирует соединение для передачи данных, но затем он может передавать байты в любое время. В чем функциональная разница? Как я уже говорил, возможность PUSH_PROMISE - это красная сельдь. Это не причина, почему HTTP / 2 является заменой для веб-сокетов. Это просто незначительная оптимизация производительности в сторону. Это не имеет ничего общего с сердцем HTTP / 2, которое является потоковым биди.
масон
1
Этот ответ просто неверен. Это путает так много аспектов, что легко запутывает. Однако суть в том, что «двунаправленные» потоки HTTP / 2 управляются запросом-ответом (и ограничены по количеству), в то время как протокол WebSockets представляет собой настоящий двунаправленный протокол на основе сообщений (он не основан на запросе-ответе, кроме фазы рукопожатия). Это огромная разница, которую нельзя преодолеть, просто неправильно прочитав спецификацию (как, кажется, @masonk и сделал непреднамеренно).
Myst
65

Я говорю «Нет» ( Websockets не устарели ).

Первая и наиболее часто игнорируемая проблема заключается в том, что HTTP / 2 push не применяется и может игнорироваться прокси, маршрутизаторами, другими посредниками или даже браузером.

т.е. (из черновика HTTP2):

Посредник может получать запросы от сервера и не перенаправлять их клиенту . Другими словами, как использовать переданную информацию, зависит от этого посредника. Точно так же посредник может решить сделать дополнительные действия для клиента без каких-либо действий со стороны сервера.

Следовательно, HTTP / 2 Push не может заменить WebSockets.

Кроме того, HTTP / 2 соединения закрываются через некоторое время.

Это правда, что стандарт гласит, что:

HTTP / 2 соединения постоянны. Для достижения максимальной производительности ожидается, что клиенты не будут закрывать соединения, пока не будет определено, что дальнейшая связь с сервером не требуется (например, когда пользователь уходит с определенной веб-страницы) или пока сервер не закроет соединение.

Но...

Серверам рекомендуется поддерживать открытые соединения как можно дольше, но при необходимости им разрешается прерывать неактивные соединения . Когда одна из конечных точек решает закрыть TCP-соединение транспортного уровня, конечная точка ДОЛЖНА сначала отправить кадр GOAWAY (раздел 6.8), чтобы обе конечные точки могли надежно определить, были ли обработаны ранее отправленные кадры, корректно завершить или завершить любые необходимые оставшиеся задачи.

Даже если одно и то же соединение позволяет передавать содержимое, пока оно открыто, и даже если HTTP / 2 решает некоторые проблемы с производительностью, вызванные «keep-alive» HTTP / 1.1 ... HTTP / 2-соединения не остаются открытыми бесконечно ,

Также веб-страница не может повторно инициировать соединение HTTP / 2 после закрытия (если только мы не вернулись к длительной работе).

РЕДАКТИРОВАТЬ (2017, два года спустя)

Реализации HTTP / 2 показывают, что несколько вкладок / окон браузера совместно используют одно соединение HTTP / 2, что означает, что pushон никогда не узнает, к какой вкладке / окну оно принадлежит, исключая использование pushв качестве замены для веб-сокетов.

РЕДАКТИРОВАТЬ (2020)

Я не уверен, почему люди начали понижать голос. Во всяком случае, годы, прошедшие с момента публикации ответа, доказали, что HTTP / 2 не может заменить WebSockets и не предназначен для этого.

Конечно, HTTP / 2 может использоваться для туннелирования соединений WebSocket, но эти туннелированные соединения все равно будут нуждаться в протоколе WebSocket, и они будут влиять на поведение контейнера HTTP / 2.

Myst
источник
4
Разъемы WS не останутся открытыми и навсегда. Различия в потоках; HTTP / 2 предоставляет вам несколько потоковых потоков, что означает, что управление потоками на сервере сильно отличается и часто не блокируется. WS (как протокол) должен иметь нерегулируемую входящую обработку. Управление потоком реализовано выше по стеку. Для безопасности и целостности сервера HTTP / 2 намного лучше, чем WS.
облигация
4
@bond, я согласен, что HTTP / 2 имеет много преимуществ в качестве транспортного уровня (совместное использование одного соединения на многих вкладках браузера является лишь одним примером). Тем не менее, он не предназначен для коммуникационного уровня . Это функциональный вопрос. Оба протокола отвечают различным потребностям. т. е. реализация sshтерминала в браузере очень проста при использовании Websockets. HTTP / 2 будет полной головной болью, особенно если открыто более одной вкладки. Кроме того, что если браузер (или один из прокси-серверов HTTP / 2) закрыл соединение? Может ли клиент просто предположить, что новые данные недоступны? мы вернулись к опросу.
Мист
1
Браузер может так же легко закрыть ваше соединение WS. Это жизнь с любым видом сетей. Если честно, мультиплексирование в HTTP / 2 излишне. Протокол действительно не нуждался в этом. Открывая несколько потоков, вы начинаете сталкиваться с проблемами, связанными с ограничением пропускной способности буферов TCP. Я согласен с вами, что WS лучше, чем HTTP / 2. По сути, WS - это то, что требует много элементов управления более высокого уровня, чтобы пользователи не могли делать плохие вещи.
облигация
2
По словам дяди Бена (Человека-паука): «Помни, с великой силой приходит большая ответственность». Да, @bond, ты очень прав. Websockets, будучи очень «сырым» протоколом, требует более ответственного проектирования сервера. И да, WS можно закрыть так же легко, как HTTP / 2, но WS поддерживает oncloseобратный вызов, поэтому опрос не требуется. Что касается мультиплексирования, я думаю, что это была необходимость, а не выбор. keep-aliveне удалось, и единственный способ избежать «первого в линии» снижения производительности - рискнуть мультиплексированием. Время покажет :)
Myst
1
С точки зрения дизайна сервера, исходящее мультиплексирование является сложной и дорогой проблемой. Это требует IO механики для внутреннего опроса, который является дорогим, как ад. Если вы не передаете большие документы, мультиплексирование даже не будет работать, потому что запрос, вероятно, полностью откликнется и буферизуется до того, как станет доступен второй, и мультиплексирование не будет выполнено. RTMP имеет исходящее мультиплексирование, но это делает только сервер Adobe. Удивительно, насколько близок HTTP / 2 к RTMP.
облигация
40

Ответ - нет. Цели между ними очень разные. Существует даже RFC для WebSocket через HTTP / 2, который позволяет вам создавать несколько соединений WebSocket через один канал HTTP / 2 TCP.

WS over HTTP / 2 будет играть роль сохранения ресурсов, уменьшая время открытия новых соединений и предоставляя больше каналов связи без дополнительных затрат на сокеты, программные прерывания и буферы.

https://tools.ietf.org/html/draft-hirano-httpbis-websocket-over-http2-01

связь
источник
Это восхитительно! Есть ли публичный пример клиента Javascript, который это реализовал? Я не могу найти никаких примеров. Что мне нужно сделать? Это хороший ресурс? undertow.io/blog/2015/04/27/An-in-depth-overview-of-HTTP2.html
RaisinBranCrunch
Кто-нибудь знает источник вышеуказанных утверждений о 1) нахождении длины заголовка, 2) нижнем регистре имен полей?
Пим Хейден
@PimHeijden обнаружение длины заголовка в HTTP / 1.x требует циклического прохождения всех байтов в поисках 4-байтового маркера конца. Это очень дорого. Независимость от регистра имен полей также означает, что любое сопоставление полей должно выполняться как для символов верхнего, так и для нижнего регистра. Это требует знания всей кодировки в верхнем и нижнем регистре для проверок. В 2.x вы можете предположить, что они строчные.
облигация
@RaisinBranCrunch Вы не можете контролировать все это из Javascript. Браузер все делает за вас.
облигация
@bond В настоящее время я использую HTTP / 2 с Nginx и proxy_pass для отправки соединений веб-сокетов на сервер сокетов, но когда у меня один пользователь открывает несколько вкладок на веб-сайте, сервер сокетов рассматривает его как несколько соединений. Я бы предположил, что если HTTP / 2 мультиплексирует соединения по одному каналу TCP, сервер будет рассматривать это как одно соединение. Это неправильно? Есть ли способ проверить, что сервер не устанавливает лишние ненужные соединения?
RaisinBranCrunch
23

Ну, цитата из этой статьи InfoQ :

Что ж, ответ однозначно отрицательный по простой причине: как мы видели выше, в HTTP / 2 вводится Server Push, который позволяет серверу активно отправлять ресурсы в кеш клиента. Однако он не позволяет передавать данные непосредственно в клиентское приложение. Серверные запросы обрабатываются только браузером и не отображаются в коде приложения, что означает, что у приложения нет API для получения уведомлений об этих событиях.

Таким образом, HTTP2 push - это нечто среднее между вашим браузером и сервером, в то время как Websockets действительно предоставляет API-интерфейсы, которые могут использоваться как клиентом (javascript, если он работает в браузере), так и кодом приложения (работает на сервере) для передачи данных в реальном времени.

Джит Пракаш
источник
5

Обмен сообщениями и простая потоковая передача (не аудио, потоковая передача видео) могут осуществляться как через мультиплексирование Http / 2, так и через WebSockets. Таким образом, есть некоторое совпадение, но WebSockets имеет хорошо установленный протокол, много фреймворков / API и меньше заголовков. Вот хорошая статья на эту тему .

Деннис Р
источник
3

На сегодняшний день нет.

HTTP / 2, по сравнению с HTTP, позволяет поддерживать соединение с сервером. Оттуда вы можете иметь несколько потоков данных одновременно. Намерение состоит в том, что вы можете нажать несколько вещей одновременно, даже если клиент не запрашивает это. Например, когда браузер запрашивает a index.html, сервер может также нажать index.cssи index.js. Браузер не просил об этом, но сервер может предоставить это без запроса, потому что он может предположить, что вы захотите через несколько секунд.

Это быстрее , чем HTTP / 1 альтернативы получения index.html, анализа его, обнаружив , что нужно index.jsи index.cssи затем строит 2 других запросов для этих файлов. HTTP / 2 позволяет серверу передавать данные, которые клиент даже не запрашивал.

В этом контексте он похож на WebSocket, но не совсем по замыслу. Предполагается, что WebSocket допускает двунаправленную связь, аналогичную TCP-соединению или последовательному соединению. Это гнездо, где оба общаются друг с другом. Кроме того, основным отличием является то, что вы можете отправлять любые произвольные пакеты данных в необработанных байтах, не инкапсулированные в протокол HTTP. Понятия заголовков, путей, строк запросов происходят только во время рукопожатия, но WebSocket открывает поток данных.

Другое отличие в том, что вы получаете гораздо более точный доступ к WebSocket в Javascript, тогда как с HTTP он обрабатывается браузером. Все, что вы получаете с HTTP, это то, что вы можете вписать в XHR/ fetch(). Это также означает, что браузер получит возможность перехватывать и изменять заголовки HTTP без возможности управления им (например Origin, Cookiesи т. Д.). Кроме того, то, что HTTP / 2 может выдвинуть, отправляется в браузер. Это означает, что JS не всегда (если вообще когда-либо) знает, что что-то толкает. Опять же, это имеет смысл index.cssи index.jsпотому, что браузер будет кешировать его, но не столько для пакетов данных.

Это действительно все во имя. HTTP означает протокол передачи гипертекста. Мы ориентированы на концепцию передачи активов. WebSocket - это создание сокетного соединения, в котором двоичные данные передаются в двух направлениях.


Единственное, что мы не обсуждаем, это SSE (Server-Sent Events). Передача данных в приложение (JS) не является целью HTTP / 2, но предназначена для SSE. SSE действительно усиливается с помощью HTTP / 2. Но это не настоящая замена WebSockets, когда важны сами данные, а не достигаемые конечные точки переменных. Для каждой конечной точки в WebSocket создается новый поток данных, но в SSE он используется совместно с уже существующим сеансом HTTP / 2.


Здесь кратко изложены цели для каждого:

  • HTTP - ответ на запрос с одним активом
  • HTTP / 2 - ответ на запрос с несколькими активами
  • SSE - ответ с потоком событий однонаправленного текста (UTF-8)
  • WebSocket - Создать двунаправленный поток двоичных данных
Короткий фитиль
источник
Страдает ли SSE в HTTP / 2 тем же ограничением, что и в HTTP1.1: ограниченное количество активных соединений на домен? (ограничение в веб-браузерах - около 5 одновременных подключений к одному и тому же имени хоста сервера, поэтому, если у вас есть 3 подключения SSE от клиента к my-server.com, у вас останется только 2 подключения для обычных запросов HTTP к одному и тому же my-server.com).
Пол-Себастьян Маноле
2

Будет реализация WebSocket в HTTP / 2. https://tools.ietf.org/html/rfc8441

Дзинтарс
источник
Нет там не будет ... подключение WebSocket будет туннелируется через HTTP / 2, но HTTP / 2 не заменит протокол, и не будет устаревать.
Мист
@ Myst Я это сказал?
Дзинтарс
2
Нет, ты не говорил этого, я сделал. Вы писали, что в HTTP / 2 будет реализована реализация WebSocket, которая, по-моему, кажется слишком короткой и вводит в заблуждение из-за того, что важные детали были опущены.
Мист
2

В настоящее время HTTP / 2 в апреле 2020 года не делает WebSockets устаревшими. Наибольшее преимущество WebSockets перед HTTP2 заключается в том, что

HTTP/2 works only on Browser Level not Application Level

Означает, что HTTP / 2 не предлагает никаких JS API, таких как WebSockets, для обеспечения связи и передачи каких-либо JSON или других данных на сервер непосредственно из приложения (например, с веб-сайта). Так что, насколько я верю, HTTP / 2 сделает WebSockets только устаревшими, если начнет предлагать API, такие как WebSockets, для взаимодействия с сервером. Пока что это просто обновленная и более быстрая версия HTTP 1.1.

воздушный
источник