Evite que su aplicación se ahogue en mensajes de WebSocket o inunde un Server de WebSocket con mensajes aplicando contrapresión.
Hintergrund
Die API de WebSocket
das WebSocket-API
proporciona una interfaz JavaScript zum WebSocket-Protokoll, lo que permite abrir una sesión de comunicación interactiva bidireccional entre el Browser von Nutzername y un servidor. Con esta API, puede enviar mensajes a un servidor y recibir respuestas basadas en eventos sin sondear el servidor para obtener una respuesta.
Die Streams-API
das Streams API
permite que JavaScript acceda mediante Programmierung a flujos de datos recibidos a través de la red y los procese como desee. Un concepto importante en el contexto de las corrientes es
Gegendruck. Dies ist der Prozess, durch den ein einzelner Strom oder eine Kette von Rohren die Geschwindigkeit des Lesens oder Schreibens reguliert. Wenn die Übertragung selbst oder eine nachfolgende Übertragung in der Pipeline noch beschäftigt ist und noch nicht bereit ist, weitere Fragmente zu akzeptieren, sendet sie ein Signal durch die Kette zurück, um die Zustellung entsprechend zu verlangsamen.
Das Problem mit der aktuellen WebSocket-API
Das Ausüben von Gegendruck auf empfangene Nachrichten ist nicht möglich
Mit der aktuellen WebSocket-API erfolgt die Reaktion auf eine Nachricht in
WebSocket.onmessage
, ein EventHandler
Wird aufgerufen, wenn eine Nachricht vom Server empfangen wird.
Angenommen, Sie haben eine Anwendung, die bei jedem Empfang einer neuen Nachricht umfangreiche Datenverarbeitungsvorgänge ausführen muss. Ich würde den Ablauf wahrscheinlich ähnlich wie im folgenden Code einrichten und seitdem erwarten
das Ergebnis der Prozess ()
Anruf, es sollte dir gut gehen, oder?
const process = asynchron (Daten) => {
Rückkehr new Promise((resolve) => {
Fenster.setTimeout(() => {
console.Log('WebSocket message processed:', Daten);
Rückkehr resolve('done');
}, 1000);
});
};webSocket.onmessage = asynchron (Veranstaltung) => {
const Daten = Veranstaltung.Daten;
erwarten process(Daten);
};
Falsch! Das Problem mit der aktuellen WebSocket-API besteht darin, dass kein Gegendruck ausgeübt werden kann. Wenn Nachrichten schneller als die kommen Prozess ()
Die Methode kann damit umgehen, der Renderprozess füllt den Speicher durch Puffern dieser Nachrichten, reagiert nicht mehr aufgrund der CPU-Auslastung bei 100% oder beidem.
Das Ausüben von Gegendruck auf gesendete Nachrichten ist nicht ergonomisch
Es ist möglich, Gegendruck auf gesendete Nachrichten auszuüben, aber es beinhaltet das Abrufen der
WebSocket.bufferedAmount
Eigentum, das ineffizient und nicht ergonomisch ist. Diese schreibgeschützte Eigenschaft gibt die Anzahl der Datenbytes zurück, die durch Aufrufe an in die Warteschlange gestellt wurden
WebSocket.send ()
, aber noch nicht an das Netzwerk übertragen. Dieser Wert wird auf Null zurückgesetzt, nachdem alle Daten in der Warteschlange gesendet wurden, aber wenn Sie weiter anrufen WebSocket.send ()
wird es weiter steigen.
Was ist die WebSocketStream-API?
Die WebSocketStream-API behebt das Problem des nicht vorhandenen oder nicht ergonomischen Gegendrucks durch die Integration von Streams in die WebSocket-API. Dies bedeutet, dass der Gegendruck ohne zusätzliche Kosten "kostenlos" ausgeübt werden kann.
Vorgeschlagene Anwendungsfälle für die WebSocketStream-API
Beispiele für Websites, die diese API verwenden können, sind:
- WebSocket-Anwendungen mit hoher Bandbreite, die Interaktivität aufrechterhalten müssen, insbesondere Video- und Bildschirmfreigabe.
- Del mismo modo, la captura de video y otras aplicaciones que generan una gran cantidad de datos en el navegador que deben cargarse en el servidor. Con contrapresión, el Klient puede dejar de producir datos en lugar de acumular datos en la memoria.
Tatsächlicher Zustand
Er ging vorbei | Bedingung |
---|---|
1. Erstellen Sie einen Erklärer | Fertigstellen |
2. Erstellen Sie eine erste Entwurfsspezifikation | In Bearbeitung |
3. Sammeln Sie Feedback und wiederholen Sie das Design | In Bearbeitung |
4. Herkunftsnachweis | Fertigstellen |
5. Starten Sie | Nicht angefangen |
Verwendung der WebSocketStream-API
Einführungsbeispiel
Die WebSocketStream-API basiert auf Versprechen, wodurch sich der Umgang damit in einer modernen JavaScript-Welt natürlich anfühlt. Beginnen Sie mit dem Aufbau eines neuen WebSocketStream
y pasándole la Url del servidor WebSocket. A continuación, espere el Verbindung
etabliert, was zu a
ReadableStream
und / oder a
WritableStream
.
Rufen Sie die
ReadableStream.getReader ()
Methode erhalten Sie endlich eine
ReadableStreamDefaultReader
, das kannst du später lesen ()
Daten von bis zum Ende der Sequenz, dh bis ein Objekt des Formulars zurückgegeben wird
{Wert: undefiniert, erledigt: wahr}
.
Folglich ruft die
WritableStream.getWriter ()
Methode erhalten Sie endlich eine
WritableStreamDefaultWriter
, das kannst du später schreiben ()
Daten a.
const wss = new WebSocketStream(WSS_URL);
const {lesbar, schreibbar} = erwarten wss.Verbindung;
const Leser = lesbar.getReader();
const writer = schreibbar.getWriter();während (wahr) {
const {Wert, erledigt} = erwarten Leser.read();
wenn (erledigt) {
brechen;
}
const result = erwarten process(Wert);
erwarten writer.write(result);
}
Gegendruck
Was ist mit der versprochenen Gegendruckfunktion? Wie ich bereits geschrieben habe, erhalten Sie es "kostenlos", ohne dass zusätzliche Schritte erforderlich sind. Ja Prozess ()
dauert länger, die nächste Nachricht wird erst verbraucht, wenn die Pipeline bereit ist. Auch der WritableStreamDefaultWriter.write ()
Der Schritt wird nur fortgesetzt, wenn dies sicher ist.
Fortgeschrittene Beispiele
Das zweite Argument für WebSocketStream ist eine Reihe von Optionen, die eine zukünftige Erweiterung ermöglichen. Derzeit ist die einzige Option Protokolle
, die sich genauso verhält wie die
zweites Argument an den WebSocket-Konstruktor:
const chatWSS = new WebSocketStream(CHAT_URL, {Protokolle: ['chat', 'chatv2']});
const {Protokoll} = erwarten chatWSS.Verbindung;
Die gewählte Protokoll
sowie Potenzial Erweiterungen
sind Teil des Wörterbuchs, das über das verfügbar ist WebSocketStream.connection
versprechen. Alle Informationen über die Live-Verbindung werden durch dieses Versprechen bereitgestellt, da es nicht relevant ist, wenn die Verbindung fehlschlägt.
const {lesbar, schreibbar, Protokoll, Erweiterungen} = erwarten chatWSS.Verbindung;
Informationen zur geschlossenen WebSocketStream-Verbindung
Die Informationen, die in der verfügbar waren
WebSocket.onclose
y
WebSocket.onerror
Ereignisse in der WebSocket-API sind jetzt über die verfügbar WebSocketStream.closed
versprechen. Das Versprechen wird im Falle eines unsauberen Abschlusses abgelehnt, andernfalls wird es mit dem vom Server gesendeten Code und Grund aufgelöst.
Alle möglichen Statuscodes und ihre Bedeutung werden in der erläutert
Liste von CloseEvent
Statuscodes.
const {code, reason} = erwarten chatWSS.geschlossen;
Schließen Sie eine WebSocketStream-Verbindung
Ein WebSocketStream kann mit einem geschlossen werden
AbortController
. Geben Sie daher a AbortSignal
zum WebSocketStream
Baumeister.
const controller = new AbortController();
const wss = new WebSocketStream(Url, {Signal: controller.Signal});
setTimeout(() => controller.abort(), 1000);
Alternativ können Sie auch die verwenden WebSocketStream.close ()
Methode, aber sein Hauptzweck ist es, Ihnen zu ermöglichen, die anzugeben
Code
und Grund, warum es an den Server gesendet wird.
wss.close({code: 4000, reason: 'Game over'});
Interoperabilidad y fortschreitende Verbesserung
Derzeit ist Chrome der einzige Browser, der die WebSocketStream-API implementiert. Für die Interoperabilität mit der klassischen WebSocket-API ist es nicht möglich, Gegendruck auf empfangene Nachrichten auszuüben. Es ist möglich, Gegendruck auf gesendete Nachrichten auszuüben, aber es beinhaltet das Abrufen der
WebSocket.bufferedAmount
Eigentum, das ineffizient und nicht ergonomisch ist.
Funktionserkennung
Verwenden Sie Folgendes, um zu überprüfen, ob die WebSocketStream-API unterstützt wird:
wenn ('WebSocketStream' im Fenster) {
}
Manifestation
In dem Browser compatibles, puede ver la API de WebSocketStream en acción en el iframe incrustado, o direkt in Glitch.
Feedback
Das Chrome-Team möchte von Ihren Erfahrungen mit der WebSocketStream-API erfahren.
Erzählen Sie uns etwas über das API-Design
Gibt es etwas in der API, das nicht wie erwartet funktioniert? Oder fehlen Ihnen Methoden oder Eigenschaften, die Sie zur Umsetzung Ihrer Idee benötigen? Haben Sie eine Frage oder einen Kommentar zum Sicherheitsmodell? Legen Sie ein Spezifikationsproblem in der entsprechenden Datei ab GitHub-Repositoryoder fügen Sie Ihre Gedanken zu einem bestehenden Problem hinzu.
Melden Sie ein Problem mit der Bereitstellung
Haben Sie einen Fehler bei der Chrome-Implementierung gefunden? Oder unterscheidet sich die Implementierung von der Spezifikation? Einen Fehler einreichen new.crbug.com. Stellen Sie sicher, dass Sie so viele Details wie möglich, einfache Anweisungen zum Reproduzieren und Eingeben enthalten Blinken> Netzwerk> WebSockets
beim Komponenten (bearbeiten) Box.
Fehler Funktioniert hervorragend für die schnelle und einfache gemeinsame Nutzung von Wiederholungsfällen.
API-Unterstützung anzeigen
Denken Sie darüber nach, die WebSocketStream-API zu verwenden? Ihr öffentlicher Support hilft dem Chrome-Team bei der Priorisierung von Funktionen und zeigt anderen Browser-Anbietern, wie wichtig es ist, diese zu unterstützen.
Sende ein Tweet zu @Cromodev mit dem #WebSocketStream
Hashtag und lassen Sie uns wissen, wo und wie Sie es verwenden.
Nützliche Links
Vielen Dank
Die WebSocketStream-API wurde von implementiert Adam Rice y
Yutaka Hirano. Heldenbild von Daan Mooij im
Unsplash.