Ich arbeite derzeit an einem Ruby on Rails- Projekt, in dem eine Liste von Bildern angezeigt wird.
Ein Muss für dieses Projekt ist, dass neue Beiträge in Echtzeit angezeigt werden, ohne dass die Webseite aktualisiert werden muss. Nach einer Weile bin ich auf einige JavaScript-Lösungen und -Dienste wie PubNub gestoßen. Keine der angebotenen Lösungen ergab jedoch einen Sinn.
In der JavaScript-Lösung ( Polling ) geschieht Folgendes:
- Benutzer 1 zeigt die Liste der Fotos an.
- Im Hintergrund fragt der JavaScript-Code jede Sekunde einen Endpunkt ab, um festzustellen, ob ein neuer Beitrag vorhanden ist.
- Benutzer 2 fügt ein neues Foto hinzu.
- Es gibt eine Verzögerung von 50 ms, bevor der neue Zyklus ausgelöst wird und die neuen Daten abruft.
- Der neue Inhalt wird in das DOM geladen .
Dies scheint seltsam, wenn man es in ein Beispiel aus der realen Welt übersetzt:
- Benutzer 1 hält einen Stapel Bilder auf seinem Schreibtisch.
- Er geht jede Sekunde zum Fotografen und fragt, ob er einen neuen hat.
- Der Fotograf macht ein neues Foto.
- In dieser Sekunde, wenn er / sie hereinkommt, kann sie das Bild aufnehmen und es auf den Stapel legen.
Meiner Meinung nach sollte die Lösung wie folgt aussehen:
- Benutzer 1 hält einen Stapel Bilder auf seinem Schreibtisch.
- Der Fotograf macht ein neues Foto.
- Der Fotograf geht zum Stapel und legt ihn mit dem Rest ab.
Die PubNub-Lösung ist im Grunde dieselbe, diesmal wird jedoch ein interner Benutzer zwischen den Parteien hin- und hergeschaltet, um die Daten gemeinsam zu nutzen.
Selbstverständlich sind beide Lösungen sehr energieaufwendig, da sie auch dann ausgelöst werden, wenn keine Daten geladen werden müssen.
Meines Wissens nach gibt es keine (logische) Erklärung, warum diese Art der Implementierung in fast jeder Echtzeitanwendung verwendet wird.
Antworten:
Pushing funktioniert gut für 1 oder eine begrenzte Anzahl von Benutzern.
Ändern Sie nun das Szenario mit einem Fotografen und 1000 Benutzern, die alle eine Kopie des Bildes wünschen. Der Fotograf muss zu 1000 Pfählen laufen. Einige von ihnen befinden sich möglicherweise in verschlossenen Büros oder sind über den gesamten Boden verteilt. Oder ihr Benutzer im Urlaub und im Moment nicht an neuen Bildern interessiert.
Der Fotograf war die ganze Zeit damit beschäftigt, spazieren zu gehen und keine neuen Bilder aufzunehmen.
Grundsätzlich gilt: Ein Pull / Poll-Modell ist für viele unzuverlässige Leser mit geringen Echtzeitanforderungen besser skalierbar (wenn ein Bild 10 Sekunden später auf einem Stapel ankommt, was ist das Problem?).
Trotzdem ist ein Push-Modell in vielen Situationen immer noch besser. Wenn Sie eine geringe Latenzzeit benötigen (Sie benötigen das neue Foto 5 Sekunden nach der Aufnahme) oder Aktualisierungen selten sind und häufige und vorhersehbare Anforderungen haben (fragen Sie den Fotografen immer alle 10 Sekunden, wenn er täglich ein neues Bild erstellt), ist das Ziehen unangemessen. Es hängt davon ab, was Sie versuchen. NASDAQ: schieben. Wetterdienst: ziehen. Hochzeitsfotograf: wohl ziehen. Nachrichtenfotoagentur: wohl schieben.
quelle
Ich bin wirklich überrascht, dass nur eine Person WebSockets erwähnt hat . Die Unterstützung ist in praktisch allen gängigen Browsern implementiert .
Tatsächlich benutzt PubNub sie. Für Ihre Anwendung würde der Browser wahrscheinlich einen Socket abonnieren, der gesendet wird, sobald ein neues Foto verfügbar ist. Der Socket würde das Foto wohlgemerkt nicht senden, sondern nur einen Link, damit der Browser es asynchron herunterladen kann.
Stellen Sie sich in Ihrem Beispiel Folgendes vor:
Dies ähnelt in etwa Ihrer ursprünglichen Beispiellösung. Dies ist effizienter als das Abfragen, da der Client keine Daten an den Server senden muss (außer möglicherweise Heartbeats ).
Auch, wie andere erwähnt haben, gibt es andere Methoden , die besser sind als einfache Abfrage , die in älteren Browsern ( longpolling, et al .)
quelle
StackExchange
Websites wie die, auf denen Sie sich gerade befinden (es sei denn, Sie betrachten diese zwischengespeicherte / gespeicherte Webseite) verwendet werdenWebSockets
. Aus diesem Grund habe ich mich auch gefragt, warum bis @korylprince niemand etwas erwähnt hatWebSockets
.Manchmal ist gut genug gut genug.
Von allen möglichen Möglichkeiten, einen "Echtzeit" -Kommunikationsprozess zu implementieren, ist das Abrufen möglicherweise die einfachste. Polling kann effektiv verwendet werden, wenn das Polling-Intervall relativ lang ist (dh Sekunden, Minuten oder Stunden statt sofort) und die durch die Überprüfung der Verbindung oder Ressource verbrauchten Taktzyklen keine Rolle spielen.
quelle
Das HTTP-Protokoll ist dahingehend beschränkt, dass der Client derjenige sein muss, der die Anforderung initiiert. Der Server kann nicht mit dem Client kommunizieren, es sei denn, er antwortet auf die Anforderung eines Clients.
Fügen Sie zum Anpassen Ihres realen Beispiels die folgende Einschränkung hinzu:
Wie würden Sie mit dieser neuen Zurückhaltung etwas anderes tun als Umfragen?
quelle
Warum werden Abstimmungen akzeptiert? Denn in Wirklichkeit ist jede Lösung ein Low-Level-Polling!
Wenn der Server Sie aktualisieren soll, sobald neue Bilder verfügbar sind, muss er in der Regel eine Verbindung zu Ihnen herstellen - da sich die IP-Adressen häufig ändern und Sie nie wissen, ob jemand kein Interesse mehr hat, muss der Client eine Art von senden Keep-Alive-Signal, zum Beispiel "Ich bin immer noch hier, ich bin nicht offline"
Alle statusbehafteten Verbindungen (z. B. TCP / IP) funktionieren gleich, da Sie nur einzelne Datenpakete über das Internet senden können. Man weiß nie, ob die andere Partei noch da ist.
Daher hat jedes Protokoll eine Zeitüberschreitung. Wenn eine Entität nicht innerhalb von X Sekunden antwortet, wird angenommen, dass sie tot ist. Selbst wenn Sie nur eine offene Verbindung zwischen Server und Client haben, ohne Daten zu senden, müssen Server und Client reguläre Keep-Alive-Pakete senden (dies wird auf niedriger Ebene gehandhabt, wenn Sie eine Verbindung zwischen ihnen herstellen) - und wie ist das? dies am Ende anders als die Umfrage?
Der beste Ansatz wäre also wahrscheinlich langwierig:
Der Client sendet sofort nach dem Laden der Site eine Anfrage (z. B. an den Fotografen "Sagen Sie mir, ob neue Bilder vorhanden sind"), der Server antwortet jedoch nicht, wenn keine neuen Bilder vorhanden sind. Sobald die Anfrage abgelaufen ist, fragt der Client erneut.
Wenn der Server jetzt neue Bilder hat, kann er sofort alle Clients beantworten, die für neue Bilder anstehen. So ist Ihre Reaktionszeit nach einem neuen Bild noch kürzer als bei Push, da der Client noch in einer offenen Verbindung auf eine Antwort wartet und Sie keine Verbindung zum Client aufbauen müssen. Und die Abrufanforderungen vom Client sind nicht viel mehr Verkehr als eine ständige Verbindung zwischen Client und Server für eine Antwort!
quelle
Ein Vorteil der Abfrage besteht darin, dass der Schaden begrenzt wird, der verursacht werden kann, wenn eine Nachricht verloren geht oder der Zustand von etwas fehlerhaft wird. Wenn X Y alle fünf Sekunden nach seinem Status fragt, führt der Verlust einer Anforderung oder einer Antwort lediglich dazu, dass die Informationen von X nicht mehr 5, sondern 10 Sekunden alt sind. Wenn Y neu gestartet wird, kann X dies im nächsten Schritt herausfinden Zeit Y ist in der Lage, auf eine der Nachrichten von X zu antworten. Wenn X neu gestartet wird, wird Y möglicherweise nie danach gefragt, aber wer den Status von X beobachtet, sollte erkennen, dass es neu gestartet wurde.
Wenn X Y nicht abfragt, sondern Y ihn benachrichtigt, sobald sich sein Status ändert, und wenn sich der Status von Y ändert und eine Nachricht an X gesendet wird, aber aus welchem Grund auch immer diese Nachricht nicht empfangen wurde, wird X die Änderung möglicherweise nie bemerken . Ebenso, wenn Y neu gestartet wird und keinen Grund hat, X eine Nachricht über irgendetwas zu senden.
In einigen Fällen kann es hilfreich sein, dass X Y auffordert, autonom Nachrichten mit seinem Status zu senden, entweder in regelmäßigen Abständen oder bei Änderungen, und nur dann eine X-Abfrage durchführt, wenn es zu lange dauert, ohne etwas von Y zu hören X muss die meisten seiner Nachrichten senden (in der Regel sollte X Y zumindest gelegentlich darüber informieren, dass es immer noch Interesse am Empfang von Nachrichten hat, und Y sollte das Senden von Nachrichten beenden, wenn es ohne Anzeichen von Interesse zu lange dauert). Ein solches Design würde jedoch erfordern, dass Y beharrlich istBehalten Sie Informationen über X bei, anstatt einfach eine Antwort an denjenigen senden zu können, der sie abgefragt hat, und vergessen Sie dann sofort, wer das war. Wenn Y ein eingebettetes System ist, kann eine solche Vereinfachung dazu beitragen, den Speicherbedarf ausreichend zu reduzieren, um die Verwendung eines kleineren und billigeren Controllers zu ermöglichen.
Polling kann einen zusätzlichen Vorteil haben, wenn ein potenziell unzuverlässiges Kommunikationsmedium (z. B. UDP oder Funk) verwendet wird: Es kann die Notwendigkeit von Bestätigungen auf Verbindungsebene weitgehend eliminieren. Wenn X Y eine Statusanforderung Q sendet, antwortet Y mit einem Statusbericht R, und X hört R, X muss keine Verbindungsschichtbestätigung hören, damit Q weiß, dass sie empfangen wurde. Umgekehrt muss Y, sobald es R sendet, nicht mehr wissen oder sich darum kümmern, ob X es empfangen hat. Wenn X eine Statusanfrage sendet und keine Antwort erhält, kann es eine andere senden. Wenn Y einen Bericht sendet und X ihn nicht hört, sendet X eine weitere Anfrage. Wenn jede Anforderung einmal ausgeht und entweder eine Antwort liefert oder nicht, muss keine Partei wissen oder sich darum kümmern, ob eine bestimmte Nachricht empfangen wurde. Da das Senden einer Bestätigung möglicherweise fast so viel Bandbreite beansprucht wie eine Statusanforderung oder ein Statusbericht, Die Verwendung eines Roundtrips von Anforderungsberichten kostet nicht viel mehr als eine unaufgeforderte Meldung und Bestätigung. Wenn X einige Anforderungen sendet, ohne Antworten zu erhalten, muss es in einigen dynamisch gerouteten Netzwerken möglicherweise Bestätigungen auf Verbindungsebene aktivieren (und in seiner Anforderung nachfragen, dass Y dies ebenfalls tut), damit der zugrunde liegende Protokollstapel das Übermittlungsproblem erkennen und suchen kann eine neue Route, aber wenn die Dinge funktionieren, ist ein Anforderungsberichtsmodell effizienter als die Verwendung von Bestätigungen auf Verbindungsebene.
quelle
Die Frage ist, wie viele unnötige Abstimmungen im Verhältnis zu unnötigen Pushs stehen.
Wenn Sie umfragen:
Wenn Sie drücken:
Es gibt verschiedene Lösungen, wie mit den verschiedenen Szenarien und ihren Nachteilen umgegangen werden kann, z. B. eine minimale Zeit zwischen Abstimmungen, reine Abstimmungs-Proxies, um das Hauptsystem zu entlasten, oder - für die Pushs - eine Verordnung, die registriert und spezifiziert werden muss die gewünschten Daten, gefolgt von der Aufhebung der Registrierung beim Abmelden. Welches am besten passt, kann man im Allgemeinen nicht sagen, es hängt vom System ab.
In Ihrem Beispiel ist Polling nicht die effizienteste, sondern die praktischste Lösung. Es ist sehr einfach, ein Abfragesystem in JavaScript zu schreiben und es ist auch auf der Bereitstellungsseite sehr einfach zu implementieren. Ein Server zur Bereitstellung von Bilddaten sollte in der Lage sein, die zusätzlichen Anforderungen zu verarbeiten. Andernfalls kann er linear skaliert werden, da die Daten zumeist statisch sind und daher problemlos zwischengespeichert werden können.
Eine Push-Methode, die eine Anmeldung, eine Beschreibung der gewünschten Daten und schließlich eine Abmeldung implementiert, wäre am effizientesten, ist aber für den durchschnittlichen "Script-Kiddy" wahrscheinlich zu komplex und muss sich mit der Frage befassen: Was ist, wenn der Benutzer Fahren Sie einfach den Browser herunter und die Abmeldung kann nicht durchgeführt werden?
Vielleicht ist es besser, mehr Benutzer zu haben (da der Zugriff einfach ist), als ein bisschen Geld auf einem anderen Cache-Server zu sparen?
quelle
Aus irgendeinem Grund scheinen heutzutage alle jüngeren Webentwickler die Lektionen der Vergangenheit vergessen zu haben und warum sich einige Dinge so entwickelt haben, wie sie es getan haben.
Angesichts dieser Einschränkungen besteht möglicherweise keine ständige wechselseitige Kommunikation. Wenn Sie sich das OSI-Modell ansehen, werden Sie feststellen, dass die meisten Überlegungen dazu dienen, die Persistenz von der zugrunde liegenden Verbindung zu entkoppeln.
Vor diesem Hintergrund ist eine Abfragemethode zum Abrufen von Informationen eine hervorragende Möglichkeit, die Bandbreite und die Rechenleistung auf der Clientseite zu reduzieren. Der Anstieg des Push ist in der Tat größtenteils nur auf den Client zurückzuführen, der ständige Abfragen durchführt, oder auf Web-Sockets. Persönlich, wenn ich alle anderen da draußen wäre, würde ich die Regelmäßigkeit der Abfrage als Mittel der Verkehrsanalyse begrüßen, bei der eine verspätete GET / POST-Anfrage einen Mann in irgendeiner mittleren Situation signalisieren würde.
quelle