Протокол WebSockets против HTTP

330

Есть много блогов и дискуссий о websocket и HTTP, и многие разработчики и сайты настоятельно рекомендуют websocket, но я до сих пор не могу понять, почему.

например (аргументы любителей websocket):

Веб-сокеты HTML5 представляют собой следующую эволюцию веб-коммуникаций - полнодуплексный, двунаправленный канал связи, который работает через один сокет в Интернете. ( http://www.websocket.org/quantum.html )

HTTP поддерживает потоковую передачу: потоковую передачу тела запроса (вы используете его при загрузке больших файлов) и потоковую передачу тела ответа.

Во время установления соединения с WebSocket клиент и сервер обмениваются данными на кадр, каждый по 2 байта, по сравнению с 8 килобайтами заголовка http при непрерывном опросе.

Почему эти 2 байта не включают в себя tcp и в соответствии с заголовками протокола tcp?

GET /about.html HTTP/1.1
Host: example.org

Это заголовок http ~ 48 байт.

http chunked encoding - https://en.wikipedia.org/wiki/Chunked_transfer_encoding :

23
This is the data in the first chunk
1A
and this is the second one
3
con
8
sequence
0
  • Таким образом, накладные расходы на каждый кусок невелики.

Кроме того, оба протокола работают по протоколу TCP, поэтому все проблемы с протоколом TCP для долговременных подключений все еще остаются.

Вопросы:

  1. Почему протокол веб-сокетов лучше?
  2. Почему это было реализовано вместо обновления протокола HTTP?
4esn0k
источник
2
Какой у Вас вопрос?
Джонас
@Jonas, 1) почему протокол websockets лучше? 2) Почему это было реализовано вместо обновления протокола HTTP? 3) Почему веб-сокеты так продвигаются?
4esn0k
@JoachimPileborg, вы можете сделать это с помощью сокетов TCP или http для настольных приложений; и вы должны использовать WebRTC для связи между браузерами и веб-
сайтами
@JoachimPileborg, это webRTC для браузера-браузера, а не веб-сокетов
4esn0k
@ 4esn0k, WS не лучше, они разные и лучше для некоторых конкретных задач. 3) Это новая функция, о которой люди должны знать и открывать новые возможности для Интернета
Jonas

Ответы:

491

1) Почему протокол WebSockets лучше?

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

Ваше 48-байтовое HTTP-рукопожатие нереально для реальных подключений через HTTP-браузер, где часто бывает несколько килобайт данных, отправленных как часть запроса (в обоих направлениях), включая множество заголовков и данных cookie. Вот пример запроса / ответа на использование Chrome:

Пример запроса (2800 байт, включая данные cookie, 490 байт без данных cookie):

GET / HTTP/1.1
Host: www.cnn.com
Connection: keep-alive
Cache-Control: no-cache
Pragma: no-cache
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.68 Safari/537.17
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: [[[2428 byte of cookie data]]]

Пример ответа (355 байт):

HTTP/1.1 200 OK
Server: nginx
Date: Wed, 13 Feb 2013 18:56:27 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: CG=US:TX:Arlington; path=/
Last-Modified: Wed, 13 Feb 2013 18:55:22 GMT
Vary: Accept-Encoding
Cache-Control: max-age=60, private
Expires: Wed, 13 Feb 2013 18:56:54 GMT
Content-Encoding: gzip

И HTTP, и WebSockets имеют начальные квитирования соединения одинакового размера, но при соединении WebSocket начальное квитирование выполняется один раз, а затем небольшие сообщения имеют только 6 байтов служебной информации (2 для заголовка и 4 для значения маски). Затраты на задержку не столько зависят от размера заголовков, сколько от логики для анализа / обработки / хранения этих заголовков. Кроме того, задержка установки TCP-соединения, вероятно, является более важным фактором, чем размер или время обработки для каждого запроса.

2) Почему это было реализовано вместо обновления протокола HTTP?

Предпринимаются усилия по реинжинирингу протокола HTTP для повышения производительности и снижения задержек, таких как SPDY , HTTP 2.0 и QUIC . Это улучшит ситуацию для обычных HTTP-запросов, но вполне вероятно, что WebSockets и / или WebRTC DataChannel будут по-прежнему иметь меньшую задержку при передаче данных между клиентами, чем протокол HTTP (или он будет использоваться в режиме, который очень похож на WebSockets). в любом случае).

Обновление :

Вот структура для размышлений о веб-протоколах:

  • TCP : транспортный уровень низкого уровня, двунаправленный, полный дуплекс и гарантированный порядок. Нет поддержки браузера (кроме как через плагин / Flash).
  • HTTP 1.0 : транспортный протокол запрос-ответ, многоуровневый по TCP. Клиент делает один полный запрос, сервер дает один полный ответ, и затем соединение закрывается. Методы запроса (GET, POST, HEAD) имеют конкретное транзакционное значение для ресурсов на сервере.
  • HTTP 1.1 : поддерживает природу ответа на запрос HTTP 1.0, но позволяет соединению оставаться открытым для нескольких полных запросов / полных ответов (один ответ на запрос). Все еще имеет полные заголовки в запросе и ответе, но соединение используется повторно и не закрывается. HTTP 1.1 также добавил некоторые дополнительные методы запроса (OPTIONS, PUT, DELETE, TRACE, CONNECT), которые также имеют определенные транзакционные значения. Однако, как отмечалось во введении к черновому предложению HTTP 2.0, конвейерная передача HTTP 1.1 не получила широкого распространения, поэтому это значительно ограничивает использование HTTP 1.1 для решения задержки между браузерами и серверами.
  • Long-poll : своего рода «взлом» HTTP (либо 1.0, либо 1.1), когда сервер не отвечает немедленно (или только частично отвечает заголовками) на запрос клиента. После ответа сервера клиент немедленно отправляет новый запрос (используя то же соединение, если через HTTP 1.1).
  • Потоковая передача HTTP : множество методов (многочастный / чанкированный ответ), которые позволяют серверу отправлять более одного ответа на один клиентский запрос. W3C стандартизирует это как отправленные сервером события, используя text/event-streamтип MIME. API браузера (который довольно похож на API WebSocket) называется API EventSource.
  • Комета / серверная рассылка : это общий термин, который включает как длинный опрос, так и потоковую передачу HTTP. Библиотеки комет обычно поддерживают несколько методов, позволяющих максимизировать кросс-браузерную и кросс-серверную поддержку.
  • WebSockets : встроенный в TCP транспортный уровень, использующий дружественное HTTP обновление рукопожатия. В отличие от TCP, который является потоковым транспортом, WebSockets - это транспорт на основе сообщений: сообщения разграничиваются по проводам и перед сборкой передаются в сборку. Соединения WebSocket являются двунаправленными, полнодуплексными и долговечными. После первоначального запроса / ответа на рукопожатие транзакционная семантика отсутствует, и для каждого сообщения накладных расходов очень мало. Клиент и сервер могут отправлять сообщения в любое время и должны обрабатывать получение сообщений асинхронно.
  • SPDY : инициированное Google предложение о расширении HTTP с использованием более эффективного проводного протокола, но с сохранением всей семантики HTTP (запрос / ответ, файлы cookie, кодирование). SPDY вводит новый формат кадрирования (с кадрами с префиксом длины) и определяет способ наложения пар HTTP-запросов / ответов на новый уровень кадрирования. Заголовки могут быть сжаты, а новые заголовки могут быть отправлены после установления соединения. Существуют реальные реализации SPDY в браузерах и на серверах.
  • HTTP 2.0 : имеет те же цели, что и SPDY: уменьшить задержку HTTP и накладные расходы при сохранении семантики HTTP. Текущий черновик взят из SPDY и определяет рукопожатие при обновлении и формирование данных, которое очень похоже на стандарт WebSocket для рукопожатия и формирования кадров. Альтернативный черновой вариант HTTP 2.0 (httpbis-speed-mobility) фактически использует WebSockets для транспортного уровня и добавляет мультиплексирование SPDY и отображение HTTP в качестве расширения WebSocket (расширения WebSocket согласовываются во время рукопожатия).
  • WebRTC / CU-WebRTC : предложения по разрешению однорангового подключения между браузерами. Это может обеспечить связь с более низкой средней и максимальной задержкой, поскольку в качестве основного транспорта используется SDP / дейтаграмма, а не TCP. Это позволяет осуществлять неупорядоченную доставку пакетов / сообщений, что позволяет избежать проблемы TCP с пиками задержки, вызванными потерянными пакетами, которые задерживают доставку всех последующих пакетов (чтобы гарантировать доставку по порядку).
  • QUIC : это экспериментальный протокол, направленный на снижение задержки в сети по сравнению с TCP. На первый взгляд, QUIC очень похож на TCP + TLS + SPDY, реализованный в UDP. QUIC обеспечивает мультиплексирование и управление потоком, эквивалентные HTTP / 2, безопасность, эквивалентную TLS, а семантику соединения, надежность и управление перегрузкой, эквивалентную TCP. Поскольку TCP реализован в ядрах операционной системы и встроенном программном обеспечении, внесение существенных изменений в TCP практически невозможно. Однако, поскольку QUIC построен поверх UDP, он не имеет таких ограничений. QUIC разработан и оптимизирован для семантики HTTP / 2.

Рекомендации :

канак
источник
1
>> Однако, это не помогает с задержкой клиента к серверу, которая требует нового соединения для каждого сообщения клиента к серверу. - как насчет потокового тела ответа? я знаю, API XMLHttpRequest не позволяет этого, но он существует. с потоковой передачей на сервер вы можете осуществлять потоковую передачу со стороны клиента.
4esn0k
8
@ Филипп, он задал вопрос, который я так или иначе хотел тщательно изучить и задокументировать. Вопрос о WebSockets против другого механизма, основанного на HTTP, поднимается довольно часто, хотя теперь есть хорошая ссылка для ссылки. Но да, похоже, что спрашивающий искал доказательства, подтверждающие предвзятое мнение о WebSockets vs HTTP, особенно потому, что он никогда не выбирал ответ и не присуждает награду.
Канака
9
Большое спасибо за этот очень хороший и точный обзор протоколов.
Мартин Мизер
2
@WardC caniuse.com предоставляет информацию о совместимости браузера (включая мобильную).
Канака
3
@ www139, нет, на уровне протокола WebSocket соединение остается открытым до тех пор, пока одна сторона или другая сторона не закроет соединение. Возможно, вам также придется беспокоиться о тайм-аутах TCP (проблема с любым протоколом на основе TCP), но любой вид трафика каждую минуту или две будет держать соединение открытым. Фактически, определение протокола WebSocket определяет тип фрейма ping / pong, хотя даже без этого вы можете отправить один байт (плюс двухбайтовый заголовок), и это сохранит соединение открытым. 2-3 байта каждые пару минут не оказывают существенного влияния на пропускную способность.
Канака
130

Вы, кажется, предполагаете, что WebSocket является заменой HTTP. Это не. Это расширение.

Основным вариантом использования WebSockets являются приложения Javascript, которые запускаются в веб-браузере и получают данные в режиме реального времени с сервера. Игры являются хорошим примером.

До появления WebSockets единственным способом взаимодействия приложений Javascript с сервером был сквозной XmlHttpRequest. Но у них есть главный недостаток: сервер не может отправлять данные, если клиент явно не запросил их.

Но новая функция WebSocket позволяет серверу отправлять данные в любое время. Это позволяет реализовывать браузерные игры с гораздо меньшими задержками и без необходимости использовать уродливые хаки, такие как AJAX long-polling или плагины для браузера.

Так почему бы не использовать обычный HTTP с потоковыми запросами и ответами

В комментарии к другому ответу вы предложили просто асинхронно передавать поток запросов и ответов клиента.

На самом деле, WebSockets в основном так. Попытка открыть соединение WebSocket от клиента вначале выглядит как HTTP-запрос, но специальная директива в заголовке (Upgrade: websocket) говорит серверу начать связь в этом асинхронном режиме. Первые наброски протокола WebSocket не были чем-то большим, и потребовалось некоторое рукопожатие, чтобы убедиться, что сервер действительно понимает, что клиент хочет общаться асинхронно. Но затем стало понятно, что прокси-серверы будут смущены этим, потому что они привыкли к обычной модели HTTP запроса / ответа. Потенциальный сценарий атаки был обнаружен на прокси - сервера. Чтобы предотвратить это, необходимо было сделать трафик WebSocket не похожим на обычный HTTP-трафик. Вот почему маскирующие ключи были введены вокончательная версия протокола .

Philipp
источник
>> Сервер не может отправлять данные, если клиент явно не запросил их .; Веб-браузер должен инициировать соединение WebSockets ... так же, как для XMLHttpRequest
4esn0k
18
@ 4esn0k Браузер инициирует соединение через веб-сокет. Но после того, как это установлено, обе стороны могут отправлять данные в любое время. Это не относится к XmlHttpRequest.
Филипп
1
ПОЧЕМУ это невозможно с HTTP?
4esn0k
4
@ Филипп, игры - хороший пример того, как блестят WebSockets. Тем не менее, это не данные в реальном времени с сервера, где вы получаете самый большой выигрыш. Вы можете получить почти такую ​​же хорошую задержку сервера-> клиента, используя потоковую передачу HTTP / длительные соединения. А с помощью долго удерживаемых запросов серверы могут эффективно отправлять всякий раз, когда у них есть данные, потому что клиент уже отправил запрос, а сервер «удерживает запрос» до тех пор, пока не получит данные. Самый большой выигрыш для WebSockets - это задержка клиента и сервера (и, следовательно, двусторонняя передача). Клиент, способный отправлять сообщения в любое время без дополнительных затрат, является реальным ключом.
Канака
1
@Philipp, еще одно примечание: помимо XMLHttpRequest и WebSockets for JavaScript существуют другие методы взаимодействия с сервером, в том числе скрытые iframes и теги сценариев с длительным опросом. Смотрите страницу кометы википедии для более подробной информации: en.wikipedia.org/wiki/Comet_(programming)
канака
27

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

HTTP

В WebSockets, хотя связь по-прежнему начинается как первоначальное HTTP-рукопожатие, она дополнительно модернизируется, чтобы следовать протоколу WebSockets (т. Е. Если сервер и клиент совместимы с протоколом, поскольку не все объекты поддерживают протокол WebSockets).

Теперь с WebSockets можно установить полный дуплекс и постоянное соединение между клиентом и сервером. Это означает, что в отличие от запроса и ответа, соединение остается открытым до тех пор, пока приложение работает (т. Е. Оно постоянно), и, поскольку оно является дуплексным, возможна двусторонняя одновременная связь, т.е. теперь сервер способен инициировать сообщение и «проталкивают» некоторые данные клиенту, когда становятся доступными новые данные (которые интересуют клиента).

WebSockets

Протокол WebSockets с отслеживанием состояния и позволяет вам реализовать шаблон обмена сообщениями «Опубликовать-подписаться» (или «Опубликовать / подписать»), который является основной концепцией, используемой в технологиях реального времени, где вы можете получать новые обновления в виде push-уведомлений сервера без клиенту приходится запрашивать (обновлять страницу) повторно. Примерами таких приложений являются отслеживание местоположения автомобиля Uber, Push-уведомления, обновление цен на фондовом рынке в режиме реального времени, чат, многопользовательские игры, живые онлайн-инструменты для совместной работы и т. Д.

Вы можете прочесть статью о глубоких погружениях в Websockets, которая объясняет историю этого протокола, как он появился, для чего он используется и как вы можете реализовать его самостоятельно.

Вот видео из презентации, которую я сделал о WebSockets и о том, чем они отличаются от использования обычных API REST: Стандартизация и использование экспоненциального роста потоков данных

Сруштика Неелакантам
источник
24

Для TL; DR вот 2 цента и более простая версия для ваших вопросов:

  1. WebSockets предоставляет следующие преимущества по сравнению с HTTP:

    • Постоянное соединение с сохранением состояния на время соединения
    • Низкая задержка: связь между сервером и клиентом практически в реальном времени благодаря отсутствию затрат на восстановление соединений для каждого запроса, как того требует HTTP.
    • Полный дуплекс: и сервер, и клиент могут отправлять / получать одновременно
  2. Протокол WebSocket и HTTP были разработаны для решения различных задач, IE WebSocket был разработан для улучшения двунаправленной связи, тогда как HTTP был разработан для того, чтобы не сохранять состояния и распространяться с использованием модели запроса / ответа. Помимо совместного использования портов по унаследованным причинам (проникновение через брандмауэр / прокси), не так много общего, чтобы объединить их в один протокол.

Devy
источник
3
Важно отметить, что вы упомянули термин «не сохраняющий состояния» и «не
имеющий
15

Почему протокол веб-сокетов лучше?

Я не думаю, что мы можем сравнить их рядом, как кто лучше. Это не будет честным сравнением просто потому, что они решают две разные проблемы . Их требования разные. Это все равно что сравнивать яблоки с апельсинами. Они разные.

HTTP является протоколом запрос-ответ. Клиент (браузер) чего-то хочет, сервер дает. То есть. Если клиент данных хочет получить большие данные, сервер может отправить потоковые данные, чтобы избежать нежелательных проблем с буфером. Здесь основное требование или проблема заключается в том, как сделать запрос от клиентов и как ответить на ресурсы (гипертекст), которые они запрашивают. Вот где блеск HTTP.

В HTTP только клиентский запрос. Сервер только отвечает.

WebSocket не является протоколом запрос-ответ, где только клиент может запросить. Это сокет (очень похож на сокет TCP). Имеется в виду, что после открытия соединения любая сторона может отправлять данные до тех пор, пока не будет закрыто подчеркивающее TCP-соединение. Это как обычная розетка. Единственное отличие от сокета TCP заключается в том, что websocket можно использовать в сети. В Интернете у нас есть много ограничений для обычного сокета. Большинство межсетевых экранов блокируют порты, отличные от 80 и 433, используемые HTTP. Прокси и посредники также будут проблематичными. Чтобы упростить развертывание протокола в существующих инфраструктурах, веб-сокет использует HTTP-рукопожатие для обновления. Это означает, что когда соединение открывается в первый раз, клиент отправляет HTTP-запрос, чтобы сообщить серверу: «Это не HTTP-запрос, пожалуйста, обновитесь до протокола websocket».

Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

Когда сервер понял запрос и обновился до протокола websocket, ни один из протоколов HTTP больше не применяется.

Так что мой ответ: ни один не лучше друг друга. Они совершенно разные.

Почему это было реализовано вместо обновления протокола HTTP?

Ну, мы можем сделать все под именем HTTP . А мы будем? Если это две разные вещи, я предпочту два разных имени. Как и Хиксон и Майкл Картер .

FranXho
источник
6

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

Протокол HTTP полностью поддерживает полнодуплексную связь; допустимо, чтобы клиент выполнял POST с передачей chunked-кодировки, а сервер возвращал ответ с телом chunked-encoding. Это позволит удалить заголовок только во время инициализации.

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

parity3
источник