Mi comprensión de HTTP Polling, Long Polling, HTTP Streaming y WebSockets

123

He leído muchas publicaciones en SO y en la web con respecto a las palabras clave en el título de mi pregunta y aprendí mucho de ellas. Algunas de las preguntas que leí están relacionadas con desafíos de implementación específicos, mientras que otras se enfocan en conceptos generales. Solo quiero asegurarme de que entendí todos los conceptos y el razonamiento por el que se inventó la tecnología X sobre la tecnología Y, etc. Así que aquí va:

Sondeo Http: Básicamente AJAX, usando XmlHttpRequest.

Http Long Polling: AJAX pero el servidor retiene la respuesta a menos que el servidor tenga una actualización, tan pronto como el servidor tiene una actualización, la envía y luego el cliente puede enviar otra solicitud. La desventaja son los datos de encabezado adicionales que deben enviarse de un lado a otro, lo que genera una sobrecarga adicional.

Http Streaming: similar al sondeo largo, pero el servidor responde con un encabezado con "Transferir codificación: fragmentado" y, por lo tanto, no necesitamos iniciar una nueva solicitud cada vez que el servidor envía algunos datos (y por lo tanto, guarda la sobrecarga adicional del encabezado). El inconveniente aquí es que tenemos que "entender" y averiguar la estructura de los datos para distinguir entre varios fragmentos enviados por el servidor.

Java Applet, Flash, Silverlight: brindan la capacidad de conectarse a servidores de socket a través de tcp / ip, pero como son complementos, los desarrolladores no quieren depender de ellos.

WebSockets: son la nueva API que intenta abordar las deficiencias de los métodos anteriores de la siguiente manera:

  • La única ventaja de WebSockets sobre complementos como Java Applets, Flash o Silverlight es que los WebSockets están integrados de forma nativa en los navegadores y no dependen de complementos.
  • La única ventaja de WebSockets sobre la transmisión http es que no tiene que hacer un esfuerzo para "comprender" y analizar los datos recibidos.
  • La única ventaja de WebSockets sobre Long Polling es la eliminación del tamaño adicional de los encabezados y la apertura y cierre de la conexión del socket a pedido.

¿Hay otras diferencias significativas que me falten? Lo siento si estoy volviendo a hacer o combinando muchas de las preguntas que ya están en SO en una sola pregunta, pero solo quiero entender perfectamente toda la información que hay en SO y en la web con respecto a estos conceptos.

¡Gracias!

Chico de software
fuente
4
Los eventos enviados por el servidor también pueden ser útiles cuando no se necesita comunicación bidireccional.
leggetter
1
Esta es una pregunta realmente útil. Creo que potencialmente sería más útil si hubiera una respuesta a la que varios autores pudieran contribuir.
leggetter
@leggetter Gracias Phil, gracias por el consejo sobre los eventos enviados por el servidor. Me interesa aprender sobre escenarios de comunicación bidireccional. Gracias.
Software Guy
1
Con HTTP Streaming y Long-Polling, necesita una segunda conexión para la comunicación bidireccional. Una conexión más duradera para el servidor -> comunicación 'push' del cliente y una segunda conexión de corta duración para el cliente -> comunicaciones del servidor. Esta segunda conexión se usa para hacer cosas como configurar y cambiar las suscripciones a los datos. Por lo tanto, EventSource se puede utilizar en una solución bidireccional y, de hecho, es una solución estandarizada nacida de HTTP Streaming y Long-Polling.
leggetter
1
Es posible que también desee consultar esta clasificación de técnicas que escribí: stackoverflow.com/questions/12078550/…
Alessandro Alinone

Respuestas:

92

Hay más diferencias que las que ha identificado.

Dúplex / direccional:

  • Unidireccional: encuesta HTTP, encuesta larga, transmisión.
  • Bi-direcitonal: WebSockets, plugin networking

En orden de latencia creciente (aproximada):

  • WebSockets
  • Complemento de redes
  • Transmisión HTTP
  • Encuesta larga HTTP
  • Sondeo HTTP

CORS (soporte de origen cruzado):

  • WebSockets: sí
  • Complemento de red: Flash mediante solicitud de política (no estoy seguro de otros)
  • HTTP * (algún soporte reciente)

Datos binarios nativos (matrices escritas, blobs):

  • WebSockets: sí
  • Complemento de red: no con Flash (requiere codificación de URL en ExternalInterface)
  • HTTP *: propuesta reciente para habilitar el soporte de tipo binario

Ancho de banda en eficiencia decreciente:

  • Red de complementos: los sockets de Flash son sin formato, excepto para la solicitud de política inicial
  • WebSockets: protocolo de enlace de configuración de conexión y unos pocos bytes por trama
  • Transmisión HTTP (reutilización de la conexión del servidor)
  • Encuesta larga HTTP: conexión para cada mensaje
  • Encuesta HTTP: conexión para cada mensaje + sin mensajes de datos

Soporte para dispositivos móviles:

  • WebSocket: iOS 4.2 y superior. Algunos Android a través de la emulación de Flash o con Firefox para Android o Google Chrome para Android, que proporcionan compatibilidad nativa con WebSocket.
  • Plugin de redes: algunos Android. No en iOS
  • HTTP *: mayormente sí

Complejidad del uso de Javascript (del más simple al más complicado). Es cierto que las medidas de complejidad son algo subjetivas.

  • WebSockets
  • Encuesta HTTP
  • Complemento de redes
  • Sondeo largo HTTP, transmisión

También tenga en cuenta que existe una propuesta del W3C para estandarizar la transmisión HTTP llamada Eventos enviados por el servidor . Actualmente se encuentra bastante temprano en su evolución y está diseñado para proporcionar una API de JavaScript estándar con una simplicidad comparable a WebSockets.

canaca
fuente
1
Muchas gracias por la agradable respuesta Kanaka. ¿Puede decirme por qué / cómo la transmisión http tiene una latencia más alta que los websockets? tal vez con un simple ejemplo? muchas gracias.
Software Guy
2
@SoftwareGuy. Muchas razones. En navegadores recientes, puede utilizar el controlador de eventos onprogress XMLHTTPRequest para recibir notificaciones de datos. Pero la especificación dice que 50 ms es el intervalo de notificación más pequeño. De lo contrario, debe sondear los datos de respuesta. Además, los envíos de clientes establecen una nueva conexión HTTP y aumentan significativamente la latencia de ida y vuelta. Además, muchos servidores web cortan las conexiones HTTP después de aproximadamente 30 segundos, lo que significa que a menudo debe restablecer la conexión push del servidor. He visto latencias de ida y vuelta de WebSocket de 5 a 10 ms en una red local. La latencia de transmisión HTTP probablemente sería de más de 50 ms.
kanaka
Muchas gracias por la respuesta detallada :)
Software Guy
1
@leggetter Gracias Phil, ¿te refieres a que enviar datos desde el cliente al servidor a través de la transmisión http causará gastos generales? ¿Es posible enviar datos al servidor a través de la transmisión http sin abrir una nueva conexión? Gracias.
Software Guy
1
¡@Nathan suena como un buen proyecto de tesis de maestría! Ciertamente, el sondeo mantendrá el sistema más ocupado que un modelo impulsado por eventos, pero cuál podría ser exactamente el ahorro de energía necesitaría pruebas empíricas bastante extensas a diferentes escalas.
kanaka
13

Algunas grandes respuestas de otros que cubren mucho terreno. Aquí tienes un poco más.

La única ventaja de WebSockets sobre complementos como Java Applets, Flash o Silverlight es que los WebSockets están integrados de forma nativa en los navegadores y no dependen de complementos.

Si con esto quiere decir que puede usar Java Applets, Flash o Silverlight para establecer una conexión de socket, entonces sí, eso es posible. Sin embargo, no lo ve implementado en el mundo real con demasiada frecuencia debido a las restricciones.

Por ejemplo, los intermediarios pueden cerrar ese tráfico y lo hacen. El estándar WebSocket fue diseñado para ser compatible con la infraestructura HTTP existente y, por lo tanto, es mucho menos propenso a ser interferido por intermediarios como firewalls y proxies.

Además, WebSocket puede usar los puertos 80 y 443 sin requerir puertos dedicados, nuevamente gracias al diseño del protocolo para ser lo más compatible posible con la infraestructura HTTP existente.

Esas alternativas de socket (Java, Flash y Silverlight) son difíciles de usar de forma segura en una arquitectura de origen cruzado. Por lo tanto, las personas que a menudo intentan usarlos de origen cruzado tolerarán las inseguridades en lugar de hacer el esfuerzo de hacerlo de forma segura.

También pueden requerir que se abran puertos "no estándar" adicionales (algo que los administradores detestan hacer) o archivos de políticas que deben administrarse.

En resumen, el uso de Java, Flash o Silverlight para la conectividad de sockets es lo suficientemente problemático como para que no lo vea implementado en arquitecturas serias con demasiada frecuencia. Flash y Java han tenido esta capacidad durante probablemente al menos 10 años y, sin embargo, no es frecuente.

El estándar WebSocket pudo comenzar con un enfoque nuevo, teniendo en cuenta esas restricciones y, con suerte, haber aprendido algunas lecciones de ellas.

Algunas implementaciones de WebSocket utilizan Flash (o posiblemente Silverlight y / o Java) como respaldo cuando no se puede establecer la conectividad de WebSocket (como cuando se ejecuta en un navegador antiguo o cuando interfiere un intermediario).

Si bien algún tipo de estrategia alternativa para esas situaciones es inteligente, incluso necesaria, la mayoría de los que usan Flash et al sufrirán los inconvenientes descritos anteriormente. No tiene por qué ser así, existen soluciones alternativas para lograr conexiones seguras con capacidad de origen cruzado utilizando Flash, Silverlight, etc., pero la mayoría de las implementaciones no lo harán porque no es fácil.

Por ejemplo, si confía en WebSocket para una conexión de origen cruzado, funcionará bien. Pero si luego ejecuta en un navegador antiguo o un firewall / proxy interfirió y confía en Flash, digamos, como su respaldo, le resultará difícil hacer esa misma conexión de origen cruzado. A menos que no le importe la seguridad, por supuesto.

Eso significa que es difícil tener una única arquitectura unificada que funcione para conexiones nativas y no nativas, a menos que esté preparado para trabajar bastante o ir con un marco que lo haya hecho bien. En una arquitectura ideal, no notaría si las conexiones fueran nativas o no; su configuración de seguridad funcionaría en ambos casos; su configuración de agrupación en clúster aún funcionaría; su planificación de capacidad aún se mantendría; y así.

La única ventaja de WebSockets sobre la transmisión http es que no tiene que hacer un esfuerzo para "comprender" y analizar los datos recibidos.

No es tan simple como abrir un flujo HTTP y sentarse mientras sus datos fluyen durante minutos, horas o más. Los diferentes clientes se comportan de manera diferente y tienes que gestionar eso. Por ejemplo, algunos clientes almacenarán los datos en búfer y no los enviarán a la aplicación hasta que se alcance algún umbral. Peor aún, algunos no pasarán los datos a la aplicación hasta que se cierre la conexión.

Por lo tanto, si envía varios mensajes al cliente, es posible que la aplicación cliente no reciba los datos hasta que se hayan recibido 50 mensajes de datos, por ejemplo. Eso no es demasiado en tiempo real.

Si bien la transmisión HTTP puede ser una alternativa viable cuando WebSocket no está disponible, no es una panacea. Se necesita una buena comprensión para trabajar de manera sólida en las tierras baldías de la Web en condiciones del mundo real.

¿Hay otras diferencias significativas que me falten?

Hay otra cosa que nadie ha mencionado todavía, así que la mencionaré.

El protocolo WebSocket fue diseñado para ser una capa de transporte para protocolos de nivel superior. Si bien puede enviar mensajes JSON o lo que sea directamente a través de una conexión WebSocket, también puede llevar protocolos estándar o personalizados.

Por ejemplo, podría hacer AMQP o XMPP a través de WebSocket, como ya lo ha hecho la gente. Por lo tanto, un cliente podría recibir mensajes de un corredor de AMQP como si estuviera conectado directamente al corredor en sí (y en algunos casos lo está).

O si tiene un servidor existente con algún protocolo personalizado, puede transportarlo a través de WebSocket, extendiendo así ese servidor de fondo a la Web. A menudo, una aplicación existente que se ha bloqueado en la empresa puede ampliar su alcance utilizando WebSocket, sin tener que cambiar la infraestructura de back-end.

(Naturalmente, querrá poder hacer todo eso de forma segura, así que consulte con el proveedor o el proveedor de WebSocket).

Algunas personas se han referido a WebSocket como TCP para la Web. Porque al igual que TCP transporta protocolos de nivel superior, también lo hace WebSocket, pero de una manera compatible con la infraestructura web.

Entonces, si bien siempre es posible enviar mensajes JSON (o lo que sea) directamente a través de WebSocket, también se deben considerar los protocolos existentes. Porque para muchas cosas que desea hacer, probablemente ya se ha pensado en un protocolo para hacerlo.

Lo siento si estoy volviendo a hacer o combinando muchas de las preguntas que ya están en SO en una sola pregunta, pero solo quiero entender perfectamente toda la información que hay en SO y en la web con respecto a estos conceptos.

Esta fue una gran pregunta, ¡y todas las respuestas han sido muy informativas!

Robin Zimmermann
fuente
Muchas gracias Robin por la excelente ayuda e información. Si puedo preguntar algo adicional: encontré un artículo en alguna parte que dice que la transmisión http también puede ser almacenada en caché por proxies, mientras que los websockets no. ¿Qué significa eso?
Software Guy
Debido a que StackOverflow limita el tamaño en los comentarios de respuesta, he dado mi respuesta a continuación: stackoverflow.com/questions/12555043/…
Robin Zimmermann
@RobinZimmermann, tu respuesta es mi favorita. +1 para la respuesta detallada realmente buena.
securecurve
10

Si puedo preguntar algo adicional: encontré un artículo en alguna parte que dice que la transmisión http también puede ser almacenada en caché por proxies, mientras que los websockets no. ¿Qué significa eso?

(StackOverflow limita el tamaño de las respuestas a los comentarios, así que tuve que responder aquí en lugar de en línea).

Ese es un buen punto. Para entender esto, piense en un escenario HTTP tradicional ... Imagine que un navegador abre una página web, por lo que solicita http://example.com , digamos. El servidor responde con HTTP que contiene el HTML de la página. Luego, el navegador ve que hay recursos en la página, por lo que comienza a solicitar archivos CSS, archivos JavaScript e imágenes, por supuesto. Todos son archivos estáticos que serán iguales para todos los clientes que los soliciten.

Algunos proxies almacenarán en caché los recursos estáticos para que las solicitudes posteriores de otros clientes puedan obtener esos recursos estáticos del proxy, en lugar de tener que volver al servidor web central para obtenerlos. Esto es almacenamiento en caché y es una gran estrategia para descargar solicitudes y procesamiento de sus servicios centrales.

Entonces el cliente # 1 solicita http://example.com/images/logo.gif , digamos. Esa solicitud pasa por el proxy hasta el servidor web central, que sirve logo.gif. A medida que logo.gif pasa a través del proxy, el proxy guardará esa imagen y la asociará con la dirección http://example.com/images/logo.gif .

Cuando aparece el cliente # 2 y también solicita http://example.com/images/logo.gif , el proxy puede devolver la imagen y no se requiere comunicación con el servidor web en el centro. Esto le da una respuesta más rápida al usuario final, lo que siempre es genial, pero también significa que hay menos carga en el centro. Eso puede traducirse en costos de hardware reducidos, costos de redes reducidos, etc. Así que es algo bueno.

El problema surge cuando logo.gif se actualiza en el servidor web. El proxy seguirá sirviendo la imagen anterior sin saber que hay una nueva imagen. Esto conduce a una cuestión de caducidad, de modo que el proxy solo almacenará en caché la imagen durante un breve período de tiempo antes de que "caduque" y la siguiente solicitud pase por el proxy al servidor web, que luego actualiza la caché del proxy. También hay soluciones más avanzadas en las que un servidor central puede enviar a cachés conocidos, y así sucesivamente, y las cosas pueden volverse bastante sofisticadas.

¿Cómo se relaciona esto con su pregunta?

Preguntó acerca de la transmisión HTTP donde el servidor está transmitiendo HTTP a un cliente. Pero la transmisión de HTTP es como HTTP normal, excepto que no deja de enviar datos. Si un servidor web sirve una imagen, envía HTTP al cliente que finalmente termina: ha enviado la imagen completa. Y si desea enviar datos, es exactamente lo mismo, pero el servidor solo envía durante mucho tiempo (como si fuera una imagen enormemente gigantesca, por ejemplo) o incluso nunca termina.

Desde el punto de vista del proxy, no puede distinguir entre HTTP para un recurso estático como una imagen o datos de la transmisión HTTP. En ambos casos, el cliente hizo una solicitud al servidor. El apoderado recordó esa solicitud y también la respuesta. La próxima vez que llegue esa solicitud, el proxy ofrecerá la misma respuesta.

Entonces, si su cliente hizo una solicitud de precios de acciones, por ejemplo, y obtuvo una respuesta, entonces el próximo cliente puede hacer la misma solicitud y obtener los datos en caché. ¡Probablemente no sea lo que quieres! Si solicita precios de acciones, desea los datos más recientes, ¿verdad?

Entonces es un problema.

Hay trucos y soluciones para manejar problemas como ese, es cierto. Obviamente, puede hacer que funcione la transmisión HTTP, ya que está en uso hoy en día. Todo es transparente para el usuario final, pero las personas que desarrollan y mantienen esas arquitecturas tienen que superar obstáculos y pagar un precio. Da como resultado arquitecturas demasiado complicadas, lo que significa más mantenimiento, más hardware, más complejidad, más costo. También significa que los desarrolladores a menudo tienen que preocuparse por algo que no deberían tener cuando solo deberían centrarse en la aplicación, la GUI y la lógica empresarial; no deberían tener que preocuparse por la comunicación subyacente.

Robin Zimmermann
fuente
1
excelente detalle Robin, muchas gracias! Realmente aprecio su completa respuesta. ¡Ya he aprendido mucho de todas las grandes personas aquí! :)
Software Guy
4

HTTP limita el número de conexiones que un cliente puede tener con un servidor a 2 (aunque esto se puede mitigar mediante el uso de subdominios) y se sabe que IE hace cumplir esto con entusiasmo. Firefox y Chrome permiten más (aunque no puedo recordar exactamente cuántos). Puede que esto no parezca un gran problema, pero si está utilizando una conexión constantemente para actualizaciones en tiempo real, todas las demás solicitudes deben atravesar el cuello de botella de la otra conexión HTTP. Y está la cuestión de tener más conexiones abiertas de los clientes que pone más carga en el servidor.

Los WebSockets son un protocolo basado en TCP y, como tal, no sufren este límite de conexión a nivel HTTP (pero, por supuesto, el soporte del navegador no es uniforme).

El jugo
fuente
gracias thejuice, así que además del problema de múltiples conexiones simultáneas como lo destacó, ¿son correctas el resto de mis suposiciones sobre los websockets?
Software Guy