¿HTTP / 2 hace obsoletos los websockets?

268

Estoy aprendiendo sobre el protocolo HTTP / 2. Es un protocolo binario con pequeños marcos de mensajes. Permite la multiplexación de secuencias a través de una única conexión TCP. Conceptualmente parece muy similar a WebSockets.

¿Hay planes para obsoletos websockets y reemplazarlos con algún tipo de solicitudes HTTP / 2 sin encabezado y mensajes push iniciados por el servidor? ¿O WebSockets complementará HTTP / 2?

vbezhenar
fuente
Creo que la respuesta aceptada es correcta, los websockets siguen siendo la solución preferida para que las aplicaciones web se comuniquen con el servidor de forma bidireccional, incluidos los mensajes enviados por el servidor. HTTP se usa para algo más que solo navegadores y cuando tanto el cliente como el servidor pueden usar API de bajo nivel, no necesitan websockets. Aún así, la mayoría de las personas usan HTTP para aplicaciones web y están más preocupadas por las API expuestas a JavaScript. Si los moderadores piensan que la respuesta aceptada debería ser diferente, no me opongo a eso, ya que esta pregunta aparentemente genera muchos puntos de vista y mi opinión podría estar equivocada.
vbezhenar

Respuestas:

162

Por lo que entendí, HTTP / 2 no es un reemplazo para websocket, sino que apunta a estandarizar el protocolo SPDY.

En HTTP / 2, server-push se utiliza detrás de escena para mejorar la carga de recursos por parte del cliente desde el navegador. Como desarrollador, realmente no te importa durante tu desarrollo. Sin embargo, con Websocket, el desarrollador puede usar una API que puede consumir y enviar mensajes con una conexión dúplex completa única.

Estas no son las mismas cosas, y deberían complementarse entre sí.

Guillaume D.
fuente
3
Gracias Guillaume por tu respuesta. Sin embargo, me pregunto si usted (o alguien) podría agregar alguna referencia de la especificación HTTP / 2. Lo que he leído de blogs, etc., con HTTP / 2, ¿existe una verdadera comunicación bidireccional?
Martin Meeser
3
No estoy seguro de que la especificación HTTP / 2 sea el lugar adecuado para dar detalles sobre los orígenes de HTTP / 2 y cómo se diferencia de Websocket. Sin embargo, puede ver fácilmente que con HTTP / 2 estamos utilizando una comunicación bidireccional: goo.gl/IJVxWS (páginas 6 y 13)
Guillaume D.
27
HTTP / 2 es de hecho bidireccional pero no simétrico, lo que significa que solo el cliente puede enviar una solicitud adecuada y el servidor puede enviar respuestas y solicitar promesas (push). Esto hace que los websockets sean diferentes en el sentido de que ambas partes son más "iguales" en términos de lo que se les permite enviar / recibir.
George Antoniadis
3
Hay un excelente podcast en la Radio de Ingeniería de Software de IEEE sobre los orígenes de HTTP2. Creo que esto es todo: se-radio.net/2015/07/episode-232-mark-nottingham-on-http2
Max Murphy
2
Una respuesta similar con una justificación completa se puede encontrar en este artículo de InfoQ aquí: infoq.com/articles/websocket-and-http2-coexist
mantrid
152

Después de terminar de leer la especificación HTTP / 2 , creo que HTTP / 2 hace obsoletos websockets para la mayoría de los casos de uso, pero tal vez no todos.

PUSH_PROMISE(coloquialmente conocido como servidor push) no es el problema aquí. Eso es solo una optimización del rendimiento.

El principal caso de uso de Websockets en un navegador es permitir la transmisión bidireccional de datos. Entonces, creo que la pregunta del OP se convierte en si HTTP / 2 hace un mejor trabajo al habilitar la transmisión bidireccional en el navegador, y creo que sí, lo hace.

En primer lugar, es bi-di. Solo lea la introducción a la sección de transmisiones :

Un "flujo" es una secuencia bidireccional independiente de tramas intercambiadas entre el cliente y el servidor dentro de una conexión HTTP / 2. Las corrientes tienen varias características importantes:

Una única conexión HTTP / 2 puede contener múltiples flujos abiertos simultáneamente, con cualquiera de los marcos de intercalación de punto final de múltiples flujos.

Las transmisiones pueden ser establecidas y utilizadas unilateralmente o compartidas por el cliente o el servidor.

Las secuencias se pueden cerrar por cualquier punto final.

Artículos como este (vinculados en otra respuesta) están equivocados sobre este aspecto de HTTP / 2. Dicen que no es bidi. Mire, hay una cosa que no puede suceder con HTTP / 2: después de abrir la conexión, el servidor no puede iniciar una transmisión normal, solo una transmisión automática. Pero una vez que el cliente abre una transmisión enviando una solicitud, ambas partes pueden enviar tramas DATA a través de un socket persistente en cualquier momento, bidi completo.

Eso no es muy diferente de websockets: el cliente debe iniciar una solicitud de actualización de websocket antes de que el servidor también pueda enviar datos.

La mayor diferencia es que, a diferencia de los websockets, HTTP / 2 define su propia semántica de multiplexación: cómo las transmisiones obtienen identificadores y cómo los marcos transportan la identificación de la transmisión en la que se encuentran. HTTP / 2 también define la semántica de control de flujo para priorizar flujos. Esto es importante en la mayoría de las aplicaciones del mundo real de bidi.

(Ese artículo equivocado también dice que el estándar Websocket tiene multiplexación. No, no lo tiene. No es realmente difícil de averiguarlo, simplemente abra el Websocket RFC 6455 y presione ⌘-F, y escriba "multiplex". Después de leer

El protocolo está destinado a ser extensible; Las versiones futuras probablemente introducirán conceptos adicionales como la multiplexación.

Encontrará que hay una extensión de borrador de 2013 para la multiplexación de Websocket. Pero no sé qué navegadores, si los hay, son compatibles con eso. No trataría de construir mi aplicación web SPA en la parte posterior de esa extensión, especialmente con HTTP / 2, el soporte nunca llegará).

La multiplexación es exactamente el tipo de cosas que normalmente debe hacer usted mismo cada vez que abre un websocket para bidi, por ejemplo, para alimentar una aplicación de una sola página que se actualiza de forma reactiva. Me alegro de que esté en la especificación HTTP / 2, cuidada de una vez por todas.

Si desea saber qué puede hacer HTTP / 2, solo mire gRPC. gRPC se implementa a través de HTTP / 2. Mire específicamente las opciones de transmisión de dúplex medio y completo que ofrece gRPC. (Tenga en cuenta que gRPC no funciona actualmente en los navegadores, pero eso es realmente porque los navegadores (1) no exponen el marco HTTP / 2 al javascript del cliente, y (2) generalmente no admiten Trailers, que se utilizan en la especificación de gRPC)

¿Dónde podrían tener un sitio websockets? El más grande es servidor-> navegador empujó datos binarios. HTTP / 2 permite servidor-> navegador empujó datos binarios, pero no está expuesto en el navegador JS. Para aplicaciones como empujar marcos de audio y video, esta es una razón para usar websockets.

Editar: 17 de enero de 2020

Con el tiempo, esta respuesta ha ido subiendo gradualmente (lo cual es bueno, porque esta respuesta es más o menos correcta). Sin embargo, todavía hay comentarios ocasionales que dicen que no es correcto por varias razones, generalmente relacionadas con cierta confusión PUSH_PROMISEo sobre cómo consumir realmente un servidor orientado a mensajes -> inserción de cliente en una aplicación de una sola página. Y hay un caso de uso para websockets en un navegador, que son datos binarios empujados por el servidor. Para datos de texto, incluido JSON, no use WebSockets, use SSE.

En resumen: el protocolo HTTP / 2 es bi-di completo. Sin embargo, los navegadores web modernos no exponen el protocolo HTTP / 2 orientado a marcos a JavaScript . Sin embargo, si realiza múltiples solicitudes al mismo origen a través de una conexión HTTP / 2, todo el tráfico se multiplexará en una conexión (¡y eso es lo que nos importa!).

Entonces, si necesita crear una aplicación de chat en tiempo real, digamos, donde necesita transmitir nuevos mensajes de chat a todos los clientes en la sala de chat que tienen conexiones abiertas, puede (y probablemente debería) hacerlo sin websockets.

Usaría Eventos enviados por el servidor para empujar los mensajes hacia abajo y la API Fetch para enviar las solicitudes hacia arriba. Server-Sent Events (SSE) es una API poco conocida pero bien soportada que expone una secuencia de servidor a cliente orientada a mensajes. Aunque no se parece al JavaScript del cliente, debajo del capó su navegador (si es compatible con HTTP / 2) reutilizará una única conexión TCP para multiplexar todos esos mensajes. No hay pérdida de eficiencia y, de hecho, es una ganancia sobre los websockets. ¿Necesitas múltiples transmisiones? ¡Abre múltiples EventSources! Se multiplexarán automáticamente por usted.

Además de ser más eficientes en cuanto a recursos y tener menos latencia inicial que un protocolo de enlace websocket, los eventos enviados por el servidor tienen la buena propiedad de que retroceden automáticamente y funcionan a través de HTTP / 1.1. Pero cuando tienes una conexión HTTP / 2, funcionan increíblemente bien.

Aquí hay un buen artículo con un ejemplo del mundo real de lograr el SPA de actualización reactiva.

masonk
fuente
21
Esta respuesta está parcialmente en desacuerdo con las otras, incluida la aceptada, y también es la mejor respuesta porque se basa en fuentes directas.
sudo
77
Estoy totalmente de acuerdo con esta respuesta y el comentario. HTTP / 2 es streambased bidireccional.
Martin Meeser
3
Respuesta realmente correcta, el tipo se molestó en verificar las fuentes y la aplicación del mundo real (grpc)
Vladimir Akopyan
1
En websockets, el servidor no puede comenzar a enviar bytes arbitrarios hasta que el cliente inicie una solicitud de actualización de websocket, pero luego puede hacerlo en cualquier momento. En HTTP / 2, el servidor no puede comenzar a enviar bytes hasta que el cliente inicie una conexión de datos, pero luego puede enviar bytes en cualquier momento. ¿Cuál es la diferencia funcional? Como he señalado, la capacidad PUSH_PROMISE es una pista falsa. No es la razón por la cual HTTP / 2 es un reemplazo para los sockets web. Es solo una optimización de rendimiento menor a un lado. No tiene nada que ver con el corazón de HTTP / 2, que es la transmisión bidireccional.
masonk
1
Esta respuesta es simplemente incorrecta. Confunde tantos aspectos que es fácilmente confuso. Sin embargo, el quid de la cuestión es que las secuencias HTTP / 2 "bidi" son impulsadas por solicitud-respuesta (y limitadas en número), mientras que el protocolo WebSockets es un verdadero protocolo bidi basado en mensajes (no se basa en solicitud-respuesta, a excepción de la fase de apretón de manos). Esta es una gran diferencia que no se puede superar simplemente leyendo mal la especificación (como parece que @masonk involuntariamente lo hizo).
Myst
65

Digo no (los Websockets no son obsoletos ).

El primer problema que se ignora con mayor frecuencia es que el empuje HTTP / 2 no es exigible y puede ser ignorado por servidores proxy, enrutadores, otros intermediarios o incluso el navegador.

es decir (del borrador HTTP2):

Un intermediario puede recibir impulsos del servidor y elegir no reenviarlos al cliente . En otras palabras, cómo hacer uso de la información enviada depende de ese intermediario. Del mismo modo, el intermediario podría optar por realizar impulsos adicionales al cliente, sin que el servidor realice ninguna acción.

Por lo tanto, HTTP / 2 Push no puede reemplazar WebSockets.

Además, las conexiones HTTP / 2 se cierran después de un tiempo.

Es cierto que el estándar establece que:

Las conexiones HTTP / 2 son persistentes. Para obtener el mejor rendimiento, se espera que los clientes no cierren las conexiones hasta que se determine que no es necesaria una comunicación adicional con un servidor (por ejemplo, cuando un usuario navega fuera de una página web en particular) o hasta que el servidor cierre la conexión.

Pero...

Se alienta a los servidores a mantener conexiones abiertas durante el mayor tiempo posible, pero se les permite terminar las conexiones inactivas si es necesario. Cuando cualquiera de los puntos finales elige cerrar la conexión TCP de la capa de transporte, el punto final de terminación DEBE enviar primero una trama GOAWAY (Sección 6.8) para que ambos puntos finales puedan determinar de manera confiable si las tramas enviadas previamente se han procesado y completar o terminar con gracia cualquier tarea restante necesaria.

Incluso si la misma conexión permite empujar contenido mientras está abierto e incluso si HTTP / 2 resuelve algunos de los problemas de rendimiento introducidos por 'keep-alive' de HTTP / 1.1 ... Las conexiones HTTP / 2 no se mantienen abiertas indefinidamente .

Tampoco puede una página web reiniciar una conexión HTTP / 2 una vez cerrada (a menos que volvamos a la extracción prolongada, claro).

EDITAR (2017, dos años después)

Las implementaciones de HTTP / 2 muestran que múltiples pestañas / ventanas del navegador comparten una única conexión HTTP / 2, lo que significa que pushnunca sabrá a qué pestaña / ventana pertenece, eliminando el uso pushcomo un reemplazo para Websockets.

EDITAR (2020)

No estoy seguro de por qué la gente comenzó a rechazar la respuesta. En todo caso, los años transcurridos desde que se publicó inicialmente la respuesta demostraron que HTTP / 2 no puede reemplazar a WebSockets y no fue diseñado para hacerlo.

Por supuesto, HTTP / 2 podría usarse para hacer un túnel de las conexiones WebSocket, pero estas conexiones tunelizadas aún requerirán el protocolo WebSocket y afectarán la forma en que se comporta el contenedor HTTP / 2.

Myst
fuente
44
Los zócalos WS tampoco permanecerán abiertos para siempre. Las diferencias son corrientes; HTTP / 2 le proporciona múltiples flujos de flujo, lo que significa que el control de flujo en el servidor es muy diferente y, a menudo, sin bloqueo. WS (como protocolo) debe tener un procesamiento entrante no regulado. El control de flujo se implementa más arriba en la pila. Por seguridad e integridad del servidor, HTTP / 2 es mucho mejor que WS.
Bono el
44
@bond, estoy de acuerdo en que HTTP / 2 tiene muchas ventajas como capa de transporte (compartir una sola conexión en muchas pestañas del navegador es solo un ejemplo). Sin embargo, no está diseñado como una capa de comunicación . Es una pregunta funcional. Ambos protocolos responden a diferentes necesidades. es decir, implementar un sshterminal en el navegador es muy sencillo cuando se usan Websockets. Sería un dolor de cabeza total en HTTP / 2, especialmente si hay más de una pestaña abierta. Además, ¿qué sucede si el navegador (o uno de los servidores proxy HTTP / 2) cierra la conexión? ¿Puede el cliente asumir que no hay nuevos datos disponibles? volvemos a las encuestas.
Myst
1
El navegador puede cerrar fácilmente su conexión WS. Así es la vida con cualquier tipo de red. Para ser sincero, la multiplexación en HTTP / 2 es exagerada. El protocolo realmente no lo necesitaba. Al abrir varias transmisiones, comienza a tener problemas con las memorias intermedias TCP que limitan el rendimiento. Estoy de acuerdo con usted en que WS es mejor en lo que hace que HTTP / 2. Básicamente, WS es algo que necesita muchos controles de nivel superior para evitar que los usuarios hagan cosas malas.
enlace
2
Para citar al tío Ben (Spider-Man): "Recuerda, con gran poder viene una gran responsabilidad". Sí, @bond, tienes mucha razón. Websockets, al ser un protocolo muy "en bruto", requiere un diseño de servidor más responsable. Y sí, WS puede cerrarse tan fácilmente como HTTP / 2, pero WS admite la onclosedevolución de llamada, por lo que no es necesario realizar encuestas. En cuanto a la multiplexación, creo que fue una necesidad más que una elección. keep-alivefalló y la única forma de evitar el golpe de rendimiento "primero en línea" era arriesgarse a la multiplexación. El tiempo lo dirá :)
Myst
1
Desde el punto de vista del diseño del servidor, la multiplexación saliente es un problema complicado y costoso. Requiere que la mecánica de IO realice encuestas internas, lo cual es caro como el infierno. A menos que esté transmitiendo documentos de gran tamaño, la multiplexación ni siquiera funcionará porque la solicitud probablemente habrá respondido y almacenado completamente internamente antes de que el segundo esté disponible y la multiplexación no se ejecute. RTMP tiene multiplexación saliente, pero solo el servidor de Adobe lo hace. Es sorprendente lo cerca que está HTTP / 2 de RTMP.
enlace
40

La respuesta es no. El objetivo entre los dos es muy diferente. Incluso hay un RFC para WebSocket sobre HTTP / 2 que le permite hacer múltiples conexiones WebSocket sobre una sola tubería TCP HTTP / 2.

WS sobre HTTP / 2 será un juego de conservación de recursos al disminuir el tiempo para abrir nuevas conexiones y permitir más canales de comunicación sin el gasto adicional de más sockets, IRQs suaves y buffers.

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

enlace
fuente
¡Eso es increíble! ¿Hay algún ejemplo público de un cliente Javascript que haya implementado esto? No puedo encontrar ningún ejemplo. ¿Qué necesitaría hacer? ¿Es este un buen recurso? undertow.io/blog/2015/04/27/An-in-depth-overview-of-HTTP2.html
RaisinBranCrunch
¿Alguien sabe una fuente de las afirmaciones anteriores acerca de 1) encontrar la longitud del encabezado, 2) minúsculas en los nombres de campo?
Pim Heijden el
@PimHeijden para detectar la longitud del encabezado en HTTP / 1.x requiere recorrer todos los bytes buscando el marcador final de 4 bytes. Esto es muy caro. La indiferencia entre mayúsculas y minúsculas de los nombres de campo también significa que cualquier coincidencia de campo debe realizarse tanto para la versión en mayúscula como en minúscula de los caracteres. Esto requiere el conocimiento de todo el juego de caracteres en mayúsculas y minúsculas para las comprobaciones. En 2.x puedes asumir que son minúsculas.
enlace
@RaisinBranCrunch No puedes controlar nada de esto desde Javascript. El navegador hace todo por ti.
Bono el
@bond Actualmente estoy usando HTTP / 2 con Nginx y proxy_pass para enviar conexiones websocket a un servidor de socket, pero cuando tengo un solo usuario que abre varias pestañas en el sitio web, el servidor de socket lo trata como conexiones múltiples. Supongo que si HTTP / 2 está multiplexando conexiones a través de una tubería TCP, el servidor lo tratará como una conexión. ¿Esto esta mal? ¿Hay alguna forma de verificar que el servidor no esté haciendo conexiones innecesarias adicionales?
RaisinBranCrunch
23

Bueno, para citar este artículo de InfoQ :

Bueno, la respuesta es claramente no, por una simple razón: como hemos visto anteriormente, HTTP / 2 introduce Server Push, que permite al servidor enviar recursos de forma proactiva a la memoria caché del cliente. Sin embargo, no permite enviar datos a la aplicación cliente. Los empujes del servidor solo son procesados ​​por el navegador y no aparecen en el código de la aplicación, lo que significa que no hay API para que la aplicación reciba notificaciones de esos eventos.

Y, por lo tanto, HTTP2 push es realmente algo entre su navegador y servidor, mientras que Websockets realmente expone las API que pueden ser utilizadas tanto por el cliente (javascript, si se ejecuta en el navegador) como por el código de la aplicación (que se ejecuta en el servidor) para transferir datos en tiempo real.

Jeet Prakash
fuente
5

El intercambio de mensajes y la transmisión simple (no audio, transmisión de video) se pueden realizar a través de multiplexación Http / 2 y WebSockets. Por lo tanto, existe cierta superposición, pero WebSockets tiene un protocolo bien establecido, muchos marcos / API y menos encabezados. Aquí hay un buen artículo sobre el tema .

Dennis R
fuente
2

Habrá implementación de WebSocket en HTTP / 2. https://tools.ietf.org/html/rfc8441

Dzintars
fuente
No, no lo hará ... la conexión WebSocket se canalizará a través de HTTP / 2, pero HTTP / 2 no reemplazará el protocolo ni quedará obsoleto.
Myst
@ Myst ¿Dije eso?
Dzintars
2
No, no dijiste eso, lo hice. Usted escribió que habrá una implementación de WebSocket en HTTP / 2, que en mi humilde opinión parecía demasiado corta y algo engañosa debido a la omisión de detalles importantes.
Myst
2

Por el momento, abril de 2020, HTTP / 2 no está volviendo obsoletos los WebSockets. La mayor ventaja de WebSockets sobre HTTP2 es que

HTTP/2 works only on Browser Level not Application Level

Significa que HTTP / 2 no ofrece ninguna API JS como WebSockets para permitir la comunicación y transferir algún tipo de JSON u otros datos directamente al servidor desde la Aplicación (por ejemplo, el sitio web). Entonces, hasta donde creo, HTTP / 2 solo hará que WebSockets quede obsoleto si comienza a ofrecer API como WebSockets para hablar con el servidor. Hasta que se trata de una versión actualizada y más rápida de HTTP 1.1.

Aireado
fuente
2

A partir de hoy, no.

HTTP / 2, en comparación con HTTP, le permite mantener una conexión con un servidor. A partir de ahí, puede tener múltiples flujos de datos al mismo tiempo. La intención es que puede empujar varias cosas al mismo tiempo, incluso sin que el cliente lo solicite. Por ejemplo, cuando un navegador solicita un index.html, el servidor también puede presionar index.cssy index.js. El navegador no lo solicitó, pero el servidor puede proporcionarlo sin que se lo soliciten porque puede suponer que lo querrá en unos segundos.

Esto es más rápido que el HTTP / 1 alternativa de obtener index.html, analizar, descubriendo que necesita index.jsy index.css, y luego construir otros 2 solicitudes de esos archivos. HTTP / 2 permite al servidor enviar datos que el cliente ni siquiera ha solicitado.

En ese contexto, es similar a WebSocket, pero no realmente por diseño. Se supone que WebSocket permite una comunicación bidireccional similar a una conexión TCP o una conexión en serie. Es un enchufe donde ambos se comunican entre sí. Además, la principal diferencia es que puede enviar paquetes de datos arbitrarios en bytes sin procesar, no encapsulados en el protocolo HTTP. Los conceptos de encabezados, rutas, cadenas de consulta solo suceden durante el protocolo de enlace, pero WebSocket abre un flujo de datos.

La otra diferencia es que obtienes un acceso mucho más ajustado a WebSocket en Javascript, mientras que con HTTP, es manejado por el navegador. Todo lo que obtienes con HTTP es lo que puedas caberXHR / fetch(). Eso también significa que el navegador se llega a interceptar y modificar las cabeceras HTTP sin que seas capaz de controlarlo (por ejemplo: Origin, Cookies, etc). Además, lo que HTTP / 2 puede empujar se envía al navegador. Eso significa que JS no siempre (si alguna vez) sabe que las cosas están siendo empujadas. Nuevamente, tiene sentido para index.cssy index.jsporque el navegador lo almacenará en caché, pero no tanto para los paquetes de datos.

Realmente todo está en el nombre. HTTP significa Protocolo de transferencia de hipertexto. Estamos orientados al concepto de transferencia de activos. WebSocket se trata de construir una conexión de socket donde los datos binarios se pasan bidireccionalmente.


El que realmente no estamos discutiendo es SSE (Eventos enviados por el servidor). Enviar datos a la aplicación (JS) no es la intención de HTTP / 2, pero es para SSE. SSE se fortalece realmente con HTTP / 2. Pero no es un reemplazo real para WebSockets cuando lo importante son los datos en sí, no los puntos finales variables que se alcanzan. Para cada punto final con WebSocket, se crea una nueva secuencia de datos, pero con SSE se comparte entre la sesión HTTP / 2 ya existente.


A continuación se resumen los objetivos para cada uno:

  • HTTP: responder a una solicitud con un activo
  • HTTP / 2: responder a una solicitud con múltiples activos
  • SSE: responda con una secuencia de eventos de texto unidireccional (UTF-8)
  • WebSocket: crea un flujo de datos binarios bidireccionales
Mecha corta
fuente