Passer au contenu principal




Evite que su aplicación se ahogue en mensajes de WebSocket o inunde un serveur de WebSocket con mensajes aplicando contrapresión.

Antécédents

La API de WebSocket

Les API WebSocket
proporciona una interfaz JavaScript afin de Protocole WebSocket, lo que permite abrir una sesión de comunicación interactiva bidireccional entre el le navigateur du Nom d'utilisateur 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.

L'API Streams

Les API Streams
permite que JavaScript acceda mediante programmation 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
contre-pression. C'est le processus par lequel un seul flux ou chaîne de tuyaux régule la vitesse de lecture ou d'écriture. Lorsque la transmission elle-même ou une transmission ultérieure dans le pipeline est toujours occupée et n'est pas encore prête à accepter plus de fragments, elle renvoie un signal à travers la chaîne pour ralentir la livraison en conséquence.

Le problème avec l'API WebSocket actuelle

Il est impossible d'appliquer une contre-pression aux messages reçus

Avec l'API WebSocket actuelle, la réaction à un message se produit dans
WebSocket.onmessage, une Gestionnaire d'événements appelé lorsqu'un message est reçu du serveur.

Supposons que vous ayez une application qui doit effectuer des opérations de traitement de données étendues à chaque fois qu'un nouveau message est reçu. Je mettrais probablement en place le flux similaire au code ci-dessous, et depuis attendre le résultat de la traiter () appel, ça devrait aller, non?


const process = asynchrone (Les données) => {
revenir new Promise((resolve) => {
la fenêtre.setTimeout(() => {
console.Journal('WebSocket message processed:', Les données);
revenir resolve('done');
}, 1000);
});
};

webSocket.onmessage = asynchrone (un événement) => {
const Les données = un événement.Les données;
attendre process(Les données);
};

Incorrect! Le problème avec l'API WebSocket actuelle est qu'il n'y a aucun moyen d'appliquer une contre-pression. Lorsque les messages arrivent plus vite que le traiter () La méthode peut les gérer, le processus de rendu remplira la mémoire en mettant ces messages en mémoire tampon, il cessera de répondre en raison de l'utilisation du processeur à 100%, ou les deux.

Appliquer une contre-pression aux messages envoyés n'est pas ergonomique

Il est possible d'appliquer une contre-pression aux messages envoyés, mais cela implique d'interroger le
WebSocket.bufferedAmount

propriété, qui est inefficace et non ergonomique. Cette propriété en lecture seule renvoie le nombre d'octets de données mis en file d'attente par les appels à
WebSocket.send (), mais pas encore transmis au réseau. Cette valeur est remise à zéro après l'envoi de toutes les données en file d'attente, mais si vous continuez d'appeler WebSocket.send (), il continuera d'augmenter.

Qu'est-ce que l'API WebSocketStream?

L'API WebSocketStream résout le problème de la contre-pression inexistante ou non ergonomique en intégrant des flux avec l'API WebSocket. Cela signifie que la contre-pression peut être appliquée «gratuitement», sans frais supplémentaires.

Cas d'utilisation suggérés pour l'API WebSocketStream

Voici quelques exemples de sites pouvant utiliser cette API:

  • Applications WebSocket à large bande passante qui doivent maintenir l'interactivité, en particulier le partage de vidéo et d'écran.
  • 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 client puede dejar de producir datos en lugar de acumular datos en la memoria.

État actuel

Il a passé État
1. Créez un explicatif Compléter
2. Créer une ébauche de spécification initiale En progrès
3. Recueillez les commentaires et répétez la conception En progrès
4. Preuve de l'origine Compléter
5. Lancez Pas commencé

Comment utiliser l'API WebSocketStream

Exemple introductif

L'API WebSocketStream est basée sur la promesse, ce qui rend sa gestion naturelle dans un monde JavaScript moderne. Commencez par construire un nouveau WebSocketStream y pasándole la URL del servidor WebSocket. A continuación, espere el lien établie, résultant en un
ReadableStream

et / ou un
WritableStream.

Appelant le
ReadableStream.getReader ()

méthode, vous obtenez enfin un
ReadableStreamDefaultReader, que plus tard tu pourras lis ()

données de jusqu'à la fin de la séquence, c'est-à-dire jusqu'à ce qu'elle renvoie un objet de la forme
{valeur: undefined, done: true}.

Par conséquent, appeler le
WritableStream.getWriter ()

méthode, vous obtenez enfin un
WritableStreamDefaultWriter, que plus tard tu pourras écrivez ()

données a.

  const wss = new WebSocketStream(WSS_URL);
const {lisible, inscriptible} = attendre wss.lien;
const lecteur = lisible.getReader();
const writer = inscriptible.getWriter();

tandis que (vrai) {
const {valeur, Fini} = attendre lecteur.read();
si (Fini) {
break;
}
const result = attendre process(valeur);
attendre writer.write(result);
}

Contre-pression

Qu'en est-il de la fonction de contre-pression promise? Comme je l'ai écrit plus tôt, vous l'obtenez "gratuitement", aucune étape supplémentaire n'est requise. Oui traiter () prend plus de temps, le message suivant ne sera consommé qu'une fois le pipeline prêt. Également WritableStreamDefaultWriter.write () L'étape ne se poursuivra que s'il est sécuritaire de le faire.

Exemples avancés

Le deuxième argument de WebSocketStream est un ensemble d'options permettant une extension future. Actuellement, la seule option est protocoles, qui se comporte de la même manière que le
deuxième argument du constructeur WebSocket:

const chatWSS = new WebSocketStream(CHAT_URL, {protocoles: ['chat', 'chatv2']});
const {protocole} = attendre chatWSS.lien;

La sélection protocole ainsi que le potentiel extensions font partie du dictionnaire disponible via le WebSocketStream.connection promettre. Toutes les informations sur la connexion en direct sont fournies par cette promesse, car elles ne sont pas pertinentes si la connexion échoue.

const {lisible, inscriptible, protocole, extensions} = attendre chatWSS.lien;

Informations sur la connexion WebSocketStream fermée

Les informations disponibles dans le
WebSocket.onclose y
WebSocket.onerror les événements de l'API WebSocket sont désormais disponibles via le WebSocketStream.closed promettre. La promesse est rejetée en cas de clôture impure, sinon elle est résolue avec le code et la raison envoyés par le serveur.

Tous les codes d'état possibles et leur signification sont expliqués dans le
Liste de CloseEvent codes d'état.

const {code, reason} = attendre chatWSS.fermé;

Fermer une connexion WebSocketStream

Un WebSocketStream peut être fermé avec un
AbortController. Par conséquent, passez un AbortSignal

au WebSocketStream constructeur.

const controller = new AbortController();
const wss = new WebSocketStream(URL, {signal: controller.signal});
setTimeout(() => controller.abort(), 1000);

Vous pouvez également utiliser le WebSocketStream.close () méthode, mais son objectif principal est de vous permettre de spécifier le
code
et la raison pour laquelle il est envoyé au serveur.

wss.close({code: 4000, reason: 'Game over'});

Interoperabilidad y mejora progresiva

Actuellement, Chrome est le seul navigateur qui implémente l'API WebSocketStream. Pour l'interopérabilité avec l'API WebSocket classique, il n'est pas possible d'appliquer une contre-pression aux messages reçus. Il est possible d'appliquer une contre-pression aux messages envoyés, mais cela implique d'interroger le
WebSocket.bufferedAmount

propriété, qui est inefficace et non ergonomique.

Détection des fonctionnalités

Pour vérifier si l'API WebSocketStream est prise en charge, utilisez:

si ('WebSocketStream' dans la fenêtre) {
}

Manifestation

Dans les navigateurs compatibles, puede ver la API de WebSocketStream en acción en el iframe incrustado, o directement dans Glitch.

Retour

L'équipe Chrome souhaite connaître vos expériences avec l'API WebSocketStream.

Parlez-nous de la conception de l'API

Y a-t-il quelque chose dans l'API qui ne fonctionne pas comme prévu? Ou vous manquez-vous des méthodes ou des propriétés dont vous avez besoin pour mettre en œuvre votre idée? Vous avez une question ou un commentaire sur le modèle de sécurité? Déposer un problème de spécification dans le Dépôt GitHubou ajoutez vos réflexions à un problème existant.

Signaler un problème avec le déploiement

Vous avez trouvé un bogue avec la mise en œuvre de Chrome? Ou la mise en œuvre est-elle différente de la spécification? Signaler un bogue dans new.crbug.com. Assurez-vous d'inclure autant de détails que possible, des instructions simples à reproduire et de saisir Clignotement> Réseau> WebSockets dans le Composants (modifier) boîte.
Échec fonctionne très bien pour un partage de cas de relecture rapide et facile.

Afficher la prise en charge de l'API

Vous envisagez d'utiliser l'API WebSocketStream? Votre assistance publique aide l'équipe Chrome à hiérarchiser les fonctionnalités et montre aux autres fournisseurs de navigateurs à quel point il est important de les prendre en charge.

Envoyer un tweeter à @Cromodev avec lui #WebSocketStream hashtag et faites-nous savoir où et comment vous l'utilisez.

Liens utiles

Merci

L'API WebSocketStream a été implémentée par Adam Rice y
Yutaka hirano. Image de héros de Daan mooij au
Unsplash.