Mein Verständnis von HTTP-Polling, Long Polling, HTTP-Streaming und WebSockets

121

Ich habe viele Beiträge auf SO und im Internet zu den Schlüsselwörtern in meinem Fragentitel gelesen und viel daraus gelernt. Einige der Fragen, die ich lese, beziehen sich auf bestimmte Implementierungsherausforderungen, während andere sich auf allgemeine Konzepte konzentrieren. Ich möchte nur sicherstellen, dass ich alle Konzepte und die Gründe verstanden habe, warum Technologie X gegenüber Technologie Y erfunden wurde und so weiter. Also los geht's:

HTTP- Abfrage: Grundsätzlich AJAX mit XmlHttpRequest.

Http Long Polling: AJAX, aber der Server behält die Antwort bei, es sei denn, der Server verfügt über ein Update. Sobald der Server über ein Update verfügt, sendet er es und der Client kann eine weitere Anforderung senden. Nachteil sind die zusätzlichen Header-Daten, die hin und her gesendet werden müssen, was zusätzlichen Overhead verursacht.

HTTP-Streaming: Ähnlich wie bei langen Abfragen, aber der Server antwortet mit einem Header mit "Transfer Encoding: chunked". Daher müssen wir nicht jedes Mal eine neue Anforderung initiieren, wenn der Server Daten sendet (und somit den zusätzlichen Header-Overhead sparen). Der Nachteil hierbei ist, dass wir die Struktur der Daten "verstehen" und herausfinden müssen, um zwischen mehreren vom Server gesendeten Chunks zu unterscheiden.

Java Applet, Flash, Silverlight: Sie bieten die Möglichkeit, über TCP / IP eine Verbindung zu Socket-Servern herzustellen. Da es sich jedoch um Plugins handelt, möchten Entwickler nicht auf sie angewiesen sein.

WebSockets: Dies ist die neue API, die versucht, die Mängel der oben genannten Methoden auf folgende Weise zu beheben:

  • Der einzige Vorteil von WebSockets gegenüber Plugins wie Java Applets, Flash oder Silverlight besteht darin, dass WebSockets nativ in Browser integriert sind und nicht auf Plugins basieren.
  • Der einzige Vorteil von WebSockets gegenüber http-Streaming besteht darin, dass Sie sich nicht bemühen müssen, die empfangenen Daten zu "verstehen" und zu analysieren.
  • Der einzige Vorteil von WebSockets gegenüber Long Polling besteht darin, dass zusätzliche Header-Größen vermieden und die Socket-Verbindung für Anforderungen geöffnet und geschlossen werden.

Gibt es noch andere signifikante Unterschiede, die mir fehlen? Es tut mir leid, wenn ich viele der bereits auf SO vorhandenen Fragen erneut stelle oder zu einer einzigen Frage kombiniere, aber ich möchte nur aus all den Informationen, die auf SO und im Internet zu diesen Konzepten verfügbar sind, einen vollkommenen Sinn machen.

Vielen Dank!

Software Guy
quelle
4
Vom Server gesendete Ereignisse sind möglicherweise auch einen Blick wert, wenn Sie keine bidirektionale Kommunikation benötigen.
Leggetter
Dies ist eine wirklich nützliche Frage. Ich denke, es wäre möglicherweise nützlicher, wenn es eine Antwort gäbe, zu der mehrere Autoren beitragen könnten.
Leggetter
@leggetter Danke Phil, danke für den Tipp bezüglich der vom Server gesendeten Ereignisse. Ich interessiere mich für bidirektionale Kommunikationsszenarien. Vielen Dank.
Software Guy
1
Bei HTTP-Streaming und Long-Polling benötigen Sie eine zweite Verbindung für die bidirektionale Kommunikation. Eine länger anhaltende Verbindung für den Server -> Client-Push-Kommunikation und eine zweite kurzlebige Verbindung für den Client -> Server-Kommunikation. Diese zweite Verbindung wird verwendet, um beispielsweise Abonnements für Daten einzurichten und zu ändern. EventSource kann also in einer bidirektionalen Lösung verwendet werden und ist tatsächlich eine standardisierte Lösung, die aus HTTP-Streaming und Long-Polling hervorgeht.
Leggetter
1
Vielleicht möchten Sie auch diese Klassifizierung der Techniken überprüfen, die ich geschrieben habe: stackoverflow.com/questions/12078550/…
Alessandro Alinone

Antworten:

91

Es gibt mehr Unterschiede als die von Ihnen identifizierten.

Duplex / Richtung:

  • Unidirektional: HTTP-Umfrage, lange Umfrage, Streaming.
  • Bidirektional: WebSockets, Plugin-Netzwerk

In der Reihenfolge zunehmender Latenz (ungefähr):

  • WebSockets
  • Plugin-Netzwerk
  • HTTP-Streaming
  • HTTP-Langzeitumfrage
  • HTTP-Abfrage

CORS (Cross-Origin-Unterstützung):

  • WebSockets: ja
  • Plugin-Netzwerk: Flash über Richtlinienanforderung (nicht sicher über andere)
  • HTTP * (einige aktuelle Unterstützung)

Native Binärdaten (typisierte Arrays, Blobs):

  • WebSockets: ja
  • Plugin-Netzwerk: nicht mit Flash (erfordert URL-Codierung über ExternalInterface)
  • HTTP *: aktueller Vorschlag zur Aktivierung der Unterstützung von Binärtypen

Bandbreite bei abnehmender Effizienz:

  • Plugin-Netzwerk: Flash-Sockets sind bis auf die anfängliche Richtlinienanforderung unformatiert
  • WebSockets: Handshake zum Verbindungsaufbau und einige Bytes pro Frame
  • HTTP-Streaming (Wiederverwendung der Serververbindung)
  • HTTP Long-Poll: Verbindung für jede Nachricht
  • HTTP-Abfrage: Verbindung für jede Nachricht + keine Datennachrichten

Unterstützung für mobile Geräte:

  • WebSocket: iOS 4.2 und höher. Einige Android-Geräte über die Flash-Emulation oder Firefox für Android oder Google Chrome für Android bieten native WebSocket-Unterstützung.
  • Plugin-Netzwerk: einige Android. Nicht unter iOS
  • HTTP *: meistens ja

Komplexität der Verwendung von Javascript (vom einfachsten bis zum kompliziertesten). Zugegebenermaßen sind Komplexitätsmaße etwas subjektiv.

  • WebSockets
  • HTTP-Umfrage
  • Plugin-Netzwerk
  • HTTP lange Umfrage, Streaming

Beachten Sie auch, dass es einen W3C-Vorschlag zur Standardisierung des HTTP-Streamings mit dem Namen Server-Sent Events gibt . Es befindet sich derzeit in einem relativ frühen Entwicklungsstadium und wurde entwickelt, um eine Standard-Javascript-API mit vergleichbarer Einfachheit wie WebSockets bereitzustellen.

Kanaka
quelle
1
Vielen Dank für die nette Antwort Kanaka. Können Sie mir bitte sagen, warum / wie http-Streaming eine höhere Latenz als Websockets hat? vielleicht mit einem einfachen Beispiel? Vielen Dank.
Software Guy
2
@ SoftwareGuy. Viele Gründe. In neueren Browsern können Sie den Ereignishandler XMLHTTPRequest onprogress verwenden, um über Daten benachrichtigt zu werden. Die Spezifikation besagt jedoch, dass 50 ms das kleinste Benachrichtigungsintervall ist. Andernfalls müssen Sie nach Antwortdaten abfragen. Außerdem stellen Client-Sends eine neue HTTP-Verbindung her und erhöhen so die Round-Trip-Latenz erheblich. Außerdem unterbrechen viele Webserver HTTP-Verbindungen nach etwa 30 Sekunden, was bedeutet, dass Sie die Server-Push-Verbindung häufig neu herstellen müssen. Ich habe 5-10 ms WebSocket-Roundtrip-Latenzen in einem lokalen Netzwerk gesehen. Die HTTP-Streaming-Latenz beträgt wahrscheinlich mehr als 50 ms.
Kanaka
Vielen Dank für die ausführliche Antwort :)
Software Guy
1
@leggetter Danke Phil, du meinst, das Senden von Daten vom Client an den Server per http-Streaming verursacht Overhead? Ist das Senden von Daten an den Server überhaupt über HTTP-Streaming möglich, ohne eine neue Verbindung herzustellen? Vielen Dank.
Software Guy
1
@ Nathan klingt nach einem guten Masterarbeitsprojekt! Abfragen werden das System zwar beschäftigter halten als ein ereignisgesteuertes Modell, aber was genau die Energieeinsparungen sein könnten, würde ziemlich umfangreiche empirische Tests in verschiedenen Maßstäben erfordern.
Kanaka
13

Einige großartige Antworten von anderen, die viel Boden abdecken. Hier ist ein bisschen mehr.

Der einzige Vorteil von WebSockets gegenüber Plugins wie Java Applets, Flash oder Silverlight besteht darin, dass WebSockets nativ in Browser integriert sind und nicht auf Plugins basieren.

Wenn Sie damit meinen, dass Sie Java Applets, Flash oder Silverlight verwenden können, um eine Socket-Verbindung herzustellen, ist dies möglich. Aufgrund der Einschränkungen wird dies jedoch nicht allzu oft in der realen Welt eingesetzt.

Zum Beispiel können und tun Vermittler diesen Verkehr herunterfahren. Der WebSocket-Standard wurde so konzipiert, dass er mit der vorhandenen HTTP-Infrastruktur kompatibel ist, und ist daher weitaus weniger anfällig für Störungen durch Vermittler wie Firewalls und Proxys.

Darüber hinaus kann WebSocket die Ports 80 und 443 verwenden, ohne dass dedizierte Ports erforderlich sind. Dies ist wiederum auf das Protokolldesign zurückzuführen, das so kompatibel wie möglich mit der vorhandenen HTTP-Infrastruktur ist.

Diese Socket-Alternativen (Java, Flash und Silverlight) sind in einer Ursprungsarchitektur nur schwer sicher zu verwenden. Daher tolerieren Menschen, die häufig versuchen, sie Cross-Origin zu verwenden, die Unsicherheiten, anstatt sich die Mühe zu machen, dies sicher zu tun.

Sie können auch das Öffnen zusätzlicher "nicht standardmäßiger" Ports (etwas, was Administratoren nicht tun möchten) oder von Richtliniendateien erfordern, die verwaltet werden müssen.

Kurz gesagt, die Verwendung von Java, Flash oder Silverlight für die Socket-Konnektivität ist problematisch genug, sodass Sie nicht feststellen, dass es in ernsthaften Architekturen zu oft bereitgestellt wird. Flash und Java haben diese Fähigkeit wahrscheinlich seit mindestens 10 Jahren und sind dennoch nicht weit verbreitet.

Der WebSocket-Standard konnte mit einem neuen Ansatz beginnen, der diese Einschränkungen berücksichtigt und hoffentlich einige Lehren daraus gezogen hat.

Einige WebSocket-Implementierungen verwenden Flash (oder möglicherweise Silverlight und / oder Java) als Fallback, wenn keine WebSocket-Konnektivität hergestellt werden kann (z. B. wenn sie in einem alten Browser ausgeführt werden oder wenn ein Vermittler eingreift).

Während eine Art Fallback-Strategie für diese Situationen klug und sogar notwendig ist, leiden die meisten, die Flash et al. Verwenden, unter den oben beschriebenen Nachteilen. Das muss nicht so sein - es gibt Problemumgehungen, um sichere Cross-Origin-fähige Verbindungen mit Flash, Silverlight usw. herzustellen -, aber die meisten Implementierungen tun dies nicht, weil es nicht einfach ist.

Wenn Sie sich beispielsweise für eine Cross-Origin-Verbindung auf WebSocket verlassen, funktioniert dies einwandfrei. Wenn Sie dann jedoch in einem alten Browser oder einer gestörten Firewall / einem gestörten Proxy ausgeführt werden und sich beispielsweise auf Flash als Fallback verlassen, fällt es Ihnen schwer, dieselbe Ursprungsverbindung herzustellen. Es sei denn, Sie kümmern sich natürlich nicht um Sicherheit.

Das bedeutet, dass es schwierig ist, eine einzige einheitliche Architektur zu haben, die für native und nicht native Verbindungen funktioniert, es sei denn, Sie sind bereit, einiges an Arbeit zu leisten oder sich für ein Framework zu entscheiden, das dies gut gemacht hat. In einer idealen Architektur würden Sie nicht bemerken, ob die Verbindungen nativ waren oder nicht; Ihre Sicherheitseinstellungen würden in beiden Fällen funktionieren. Ihre Clustering-Einstellungen würden weiterhin funktionieren. Ihre Kapazitätsplanung würde noch halten; und so weiter.

Der einzige Vorteil von WebSockets gegenüber http-Streaming besteht darin, dass Sie sich nicht bemühen müssen, die empfangenen Daten zu "verstehen" und zu analysieren.

Es ist nicht so einfach, einen HTTP-Stream zu öffnen und sich zurückzulehnen, während Ihre Daten Minuten, Stunden oder länger fließen. Unterschiedliche Kunden verhalten sich unterschiedlich und das müssen Sie verwalten. Beispielsweise puffern einige Clients die Daten und geben sie erst dann an die Anwendung weiter, wenn ein bestimmter Schwellenwert erreicht ist. Schlimmer noch, einige geben die Daten erst an die Anwendung weiter, wenn die Verbindung geschlossen ist.

Wenn Sie also mehrere Nachrichten an den Client senden, wird die Clientanwendung die Daten möglicherweise erst empfangen, wenn beispielsweise Daten im Wert von 50 Nachrichten empfangen wurden. Das ist nicht zu Echtzeit.

Während HTTP-Streaming eine praktikable Alternative sein kann, wenn WebSocket nicht verfügbar ist, ist es kein Allheilmittel. Es braucht ein gutes Verständnis, um unter realen Bedingungen auf robuste Weise im Ödland des Web zu arbeiten.

Gibt es noch andere signifikante Unterschiede, die mir fehlen?

Es gibt noch eine andere Sache, die noch niemand erwähnt hat, also werde ich sie ansprechen.

Das WebSocket-Protokoll wurde als Transportschicht für übergeordnete Protokolle konzipiert. Sie können JSON-Nachrichten oder was nicht direkt über eine WebSocket-Verbindung senden, es können jedoch auch Standard- oder benutzerdefinierte Protokolle übertragen werden.

Sie können beispielsweise AMQP oder XMPP über WebSocket ausführen, wie dies bereits geschehen ist. Ein Client kann also Nachrichten von einem AMQP-Broker empfangen, als wäre er direkt mit dem Broker selbst verbunden (und in einigen Fällen auch).

Wenn Sie über einen vorhandenen Server mit einem benutzerdefinierten Protokoll verfügen, können Sie diesen über WebSocket transportieren und so diesen Back-End-Server auf das Web ausweiten. Häufig kann eine vorhandene Anwendung, die im Unternehmen gesperrt wurde, ihre Reichweite mithilfe von WebSocket erweitern, ohne dass die Back-End-Infrastruktur geändert werden muss.

(Natürlich möchten Sie dies alles sicher tun können. Wenden Sie sich daher an den Anbieter oder den WebSocket-Anbieter.)

Einige Leute haben WebSocket als TCP für das Web bezeichnet. Denn genau wie TCP übergeordnete Protokolle transportiert, überträgt auch WebSocket Protokolle, die jedoch mit der Webinfrastruktur kompatibel sind.

Während das Senden von JSON-Nachrichten (oder was auch immer) direkt über WebSocket immer möglich ist, sollten auch vorhandene Protokolle berücksichtigt werden. Denn für viele Dinge, die Sie tun möchten, gibt es wahrscheinlich ein Protokoll, an das bereits gedacht wurde.

Es tut mir leid, wenn ich viele der bereits auf SO vorhandenen Fragen erneut stelle oder zu einer einzigen Frage kombiniere, aber ich möchte nur aus all den Informationen, die auf SO und im Internet zu diesen Konzepten verfügbar sind, einen vollkommenen Sinn machen.

Dies war eine großartige Frage, und die Antworten waren alle sehr informativ!

Robin Zimmermann
quelle
Vielen Dank Robin für die hervorragende Hilfe und Info. Wenn ich noch etwas fragen darf: Ich bin irgendwo in einem Artikel darauf gestoßen, dass http-Streaming möglicherweise auch von Proxys zwischengespeichert wird, während dies bei Websockets nicht der Fall ist. was bedeutet das?
Software Guy
Da StackOverflow die Größe in Antwortkommentaren begrenzt, habe ich meine Antwort unten gegeben: stackoverflow.com/questions/12555043/…
Robin Zimmermann
@RobinZimmermann, deine Antwort ist meine Lieblingsantwort. +1 für die wirklich gute detaillierte Antwort.
Securecurve
10

Wenn ich noch etwas fragen darf: Ich bin irgendwo in einem Artikel darauf gestoßen, dass http-Streaming möglicherweise auch von Proxys zwischengespeichert wird, während dies bei Websockets nicht der Fall ist. was bedeutet das?

(StackOverflow begrenzt die Größe der Kommentarantworten, daher musste ich hier eher antworten als inline.)

Das ist ein guter Punkt. Um dies zu verstehen, denken Sie an ein traditionelles HTTP-Szenario ... Stellen Sie sich vor, ein Browser hat eine Webseite geöffnet und fordert beispielsweise http://example.com an . Der Server antwortet mit HTTP, das den HTML-Code für die Seite enthält. Dann sieht der Browser, dass die Seite Ressourcen enthält, und fordert natürlich die CSS-Dateien, JavaScript-Dateien und Bilder an. Dies sind alles statische Dateien, die für alle Clients, die sie anfordern, gleich sind.

Einige Proxys speichern statische Ressourcen zwischen, sodass nachfolgende Anforderungen von anderen Clients diese statischen Ressourcen vom Proxy abrufen können, anstatt vollständig zum zentralen Webserver zurückkehren zu müssen, um sie abzurufen. Dies ist Caching und eine großartige Strategie, um Anforderungen und Verarbeitung von Ihren zentralen Diensten zu verlagern.

Client Nr. 1 fordert also beispielsweise http://example.com/images/logo.gif an . Diese Anfrage geht über den Proxy bis zum zentralen Webserver, auf dem logo.gif bereitgestellt wird. Wenn logo.gif den Proxy durchläuft, speichert der Proxy das Bild und ordnet es der Adresse http://example.com/images/logo.gif zu .

Wenn Client Nr. 2 kommt und auch http://example.com/images/logo.gif anfordert , kann der Proxy das Image zurückgeben und es ist keine Kommunikation zum Webserver in der Mitte erforderlich. Dies gibt dem Endbenutzer eine schnellere Reaktion, was immer großartig ist, aber es bedeutet auch, dass das Zentrum weniger belastet wird. Dies kann zu geringeren Hardwarekosten, geringeren Netzwerkkosten usw. führen. Das ist also eine gute Sache.

Das Problem tritt auf, wenn das logo.gif auf dem Webserver aktualisiert wird. Der Proxy wird weiterhin das alte Image bereitstellen, ohne zu wissen, dass ein neues Image vorhanden ist. Dies führt zu einem vollständigen Ablauf, sodass der Proxy das Image nur für kurze Zeit zwischenspeichert, bevor es "abläuft" und die nächste Anforderung über den Proxy an den Webserver gesendet wird, der dann den Cache des Proxys aktualisiert. Es gibt auch fortschrittlichere Lösungen, bei denen ein zentraler Server auf bekannte Caches usw. zugreifen kann und die Dinge ziemlich komplex werden können.

Wie passt das zu Ihrer Frage?

Sie haben nach dem HTTP-Streaming gefragt, bei dem der Server HTTP an einen Client überträgt. Das Streaming von HTTP ist jedoch genauso wie normales HTTP, außer dass Sie nicht aufhören, Daten zu senden. Wenn ein Webserver ein Image bereitstellt, sendet er HTTP an den Client, der schließlich endet: Sie haben das gesamte Image gesendet. Und wenn Sie Daten senden möchten, ist es genau das Gleiche, aber der Server sendet nur für eine sehr lange Zeit (als wäre es beispielsweise ein enorm gigantisches Bild) oder wird sogar nie fertig.

Aus Sicht des Proxys kann nicht zwischen HTTP für eine statische Ressource wie ein Image oder Daten aus HTTP-Streaming unterschieden werden. In beiden Fällen hat der Client eine Anfrage an den Server gestellt. Der Proxy erinnerte sich an diese Anfrage und auch an die Antwort. Wenn diese Anforderung das nächste Mal eingeht, liefert der Proxy dieselbe Antwort.

Wenn Ihr Kunde beispielsweise eine Anfrage nach Aktienkursen gestellt und eine Antwort erhalten hat, kann der nächste Kunde dieselbe Anfrage stellen und die zwischengespeicherten Daten abrufen. Wahrscheinlich nicht was du willst! Wenn Sie Aktienkurse anfordern, möchten Sie die neuesten Daten, richtig?

Es ist also ein Problem.

Es gibt Tricks und Problemumgehungen, um solche Probleme zu lösen. Natürlich können Sie HTTP-Streaming zum Laufen bringen, da es heute verwendet wird. Für den Endbenutzer ist alles transparent, aber die Leute, die diese Architekturen entwickeln und warten, müssen durch die Reifen springen und einen Preis zahlen. Dies führt zu überkomplizierten Architekturen, was mehr Wartung, mehr Hardware, mehr Komplexität und mehr Kosten bedeutet. Dies bedeutet auch, dass Entwickler sich häufig um etwas kümmern müssen, das sie nicht müssen sollten, wenn sie sich nur auf die Anwendung, die grafische Benutzeroberfläche und die Geschäftslogik konzentrieren sollten - sie sollten sich nicht um die zugrunde liegende Kommunikation kümmern müssen.

Robin Zimmermann
quelle
1
exzellentes Detail Robin, vielen Dank! Ich freue mich sehr über Ihre gründliche Antwort. Ich habe schon so viel von all den tollen Leuten hier gelernt! :)
Software Guy
4

HTTP begrenzt die Anzahl der Verbindungen, die ein Client mit einem Server haben kann, auf 2 (obwohl dies durch die Verwendung von Subdomains verringert werden kann), und es ist bekannt, dass der IE dies eifrig erzwingt. Firefox und Chrome erlauben mehr (obwohl ich mich nicht genau erinnern kann, wie viele es sind). Dies scheint kein großes Problem zu sein. Wenn Sie jedoch ständig eine Verbindung für Echtzeitaktualisierungen verwenden, müssen alle anderen Anforderungen über die andere HTTP-Verbindung einen Engpass aufweisen. Und es geht darum, dass offenere Verbindungen von Clients den Server stärker belasten.

WebSockets sind ein TCP-basiertes Protokoll und leiden daher nicht unter dieser Verbindungsbeschränkung auf HTTP-Ebene (aber die Browserunterstützung ist natürlich nicht einheitlich).

Der Saft
quelle
danke thejuice, sind also neben dem von Ihnen hervorgehobenen Problem der gleichzeitigen Verbindung mehrerer Verbindungen die restlichen Annahmen in Bezug auf Websockets korrekt?
Software Guy