После того, как я закончил читать спецификацию 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 с реактивно-обновляемым обновлением.