33
Le protocole WAMP.ws Avec Autobahn + Crossbar.io

Présentation de WAMP.ws, le protocole pour faire du PUB/SUB et RPC over Websocket

Embed Size (px)

Citation preview

Le protocole

WAMP.ws

Avec

Autobahn + Crossbar.io

WAMP protocol(Web Application Messaging Protocol)

≠WAMP server stack

(Windows, Apache, MySQL, PHP)

WAMP.wsest un protocole créé pour tirer parti des

websockets

(http://wamp.ws/)

Il permet de faire communiquer en temps réel des technologies différentes ainsi que des

processus et machines différentes.

WAMP.ws offre deux outils

RPC

PUB/SUB

Depuis et vers :

● JS (Node et Navigateur)● Python (pur)● C++● Java● Objective-C● PHP● C#

&

RPC : Remote Procedure Call

● Permet d'appeler une fonction d'un autre code à distance à travers une websocket.

● Asynchrone, performant, propre, léger. Mais simple.● Paramètres et valeurs de retour peuvent être :

arrays, maps, nombres et chaînes.● Marche entre deux langages différents.● Marche entre processus locaux ou à travers

internet.

RPC – Exemple 1Tout ce qu'on fait d'habitude avec AJAX

Navigateur

Comme un GET /user/profile, mais plus rapide puisque via Websocket.

Serveur

getUserProfile()

{'user' : 'sam', 'id' : 1}

RPC

RPC – Exemple 2Communication entre navigateurs

Navigateur de Sam

Si on code un jeu d'échecs et que je bouge un pion, mon navigateur peut dire directement à celui de Max de bouger le pion sur son écran.

moveQueen('A', '5')

RPCNavigateur

de Max

RPC – Exemple 3Push de données vers le navigateur

Si on code un jeu d'échecs avec une intelligence artificielle et que c'est au tour du bot, il peut directement dire au navigateur du joueur humain de bouger le pion sur son écran.

moveQueen('A', '5')

RPCNavigateur Serveur

RPC – Exemple 4Microservices

Plutôt que d'avoir une grosse application centrale qui fait tout, on peut avoir plusieurs processus séparés qui font chacun une tâche. Avantage : on peut les réutiliser, les partager entre

projets, les redémarrer indépendamment, les répartir sur plusieurs serveurs...

moveQueen('A', '5')

RPC

Navigateur

Auth IA ChatCompétition

SendMsg('yolo')getPool()login()

RPC – Exemple 5Y a pas que le navigateur dans la vie

Différents services peuvent communiquer entre eux par le même biais. Même protocole, mêmeAPI, quels que soient les langages dans lesquels ils sont écrits. Qu'ils soient sur le même serveur

ou non. On peut ainsi déléguer des tâches sur d'autres services, ou machines.

RPC

PythonRasberry Pi

NodeJSArduino

getVideo()

toggleLED()

Montrez-moi le code !

Voici un exemple simple d'un navigateur appelant une fonction définie dans un autre navigateur.

Résultat vouluIndex.html

button.html

RPC

Callback

Réponse

index.html<!DOCTYPE html><html> <head> <script src="https://autobahn.s3.amazonaws.com/autobahnjs/latest/autobahn.min.jgz" type="text/javascript"></script></head><body><p id="baby">Appelez callMeMaybe() depuis un autre navigateur :)</p></body><script>// Connexion au serveur de test WAMP.var connection = new autobahn.Connection({ url: 'wss://demo.crossbar.io/ws', realm: 'realm1'});

// Lancer ce code une fois que la connexion est réussie.connection.onopen = function (session) { // On déclare que cette fonction est appelable // par un autre client session.register('callMeMaybe', function(message){ // On change le contenu de la page. document.getElementById('baby').innerHTML = message // On retourne la userAgent du navigateur comme ça vous pouvez // tester sur 2 nav différents et voir qu'ils communiquent return navigator.userAgent; });};

// Ouvrir la connexion.connection.open();</script></html>

button.html<!DOCTYPE html><html> <head> <script src="https://autobahn.s3.amazonaws.com/autobahnjs/latest/autobahn.min.jgz" type="text/javascript"></script></head><body><p><button onClick='callIt()'>Call It, bobby !</button></p></body><script>// Connexion au serveur de test WAMP.var connection = new autobahn.Connection({ url: 'wss://demo.crossbar.io/ws', realm: 'realm1'});

// Lancer ce code une fois que la connexion est réussie.connection.onopen = function(session) { callIt = function(){ /* Appel de la fonction callMeMaybe() sur l'autre nav */ session.call("callMeMaybe", ['I called baby !']) /* L'appel retourne une promesse */ .then(function(userAgent){ alert(userAgent); }); return false; }};

// Ouvrir la connexion.connection.open();</script></html>

Comment ça marche ?

● Chaque code utilisant WAMP.ws est un client qui a besoin d'une bibliothèque dédiée à cela.

● Il faut un serveur central, entre tous les clients. Comme avec RabbitMQ pour AMQP. Ce n'est pas du P2P à la WebRTC.

● Les libs et le serveur sont libres, à disposition, prêts à l'usage.

● Il existe des moyens de sécurisation (permissions, chiffrement). Ceci est une démo simple.

RPC – Sous le capotCommunication entre navigateurs

Navigateur de Sam

Même si on ne le voit pas en codant, il y a un routeur qui transmet les messages. Il faut ce routeur installé quelque part pour que WAMP fonctionne.

Navigateur de Max

moveQueen('A', '5')

Routeur

RPC – Sous le capotCommunication entre navigateurs

AutoBahnJS

moveQueen('A', '5')

AutoBahnJSCrossbar.io

AutobahnX (AutobahnPython, AutobahnJS, AutobanCpp…) sont les noms des libs les plus utilisées pour permettre à votre code, le client, de parler WAMP.

Crossbar.io est le nom du routeur le plus complet.

Pour vous

● Vous allez uniquement coder le client, avec une des bibliothèques Autobahn.

● Pour vos tests vous pouvez utiliser le routeur de démonstration (wss://demo.crossbar.io/ws). Il n'y a rien à installer.

● En production, vous installez crossbar.io. Un peu comme on installe Apache ou Nginx pour faire du HTTP.

PUB/SUB

● Un client s'abonne (SUBscribe) à un sujet.

● Un autre client publie un message (PUBlish) sur ce sujet.

● Tous les clients abonnés à ce sujet en particulier reçoivent le message.

PUB/SUB

● Un client s'abonne (SUBscribe) à un sujet.● Un autre client publie un message (PUBlish) sur ce

sujet.● Tous les clients abonnés à ce sujet en particulier

reçoivent le message.

Même principe que RPC, mais permet d'envoyer un messages à 0 ou N clients, pas juste 1. Néanmoins, il n'y a pas de valeur de retour possible.

PUB/SUB – Exemple 1Notifications

Navigateur

Le serveur vient de mettre à disposition une nouvelle vidéo. Tous les navigateurs reçoivent immédiatement l'information et l'affichent sur la page.

Serveur

{'title: 'Chat rigolo', 'id' : 2}

SUB : abonnés au sujet « nouvelle vidéo »

Navigateur Navigateur

PUB

PUB/SUB – Exemple 2Synchronisation

Web Crawler

Tous vos composants sont toujours au courant de tout ce qu'ils doivent savoir, où qu'ils soient. Ici, si l'admin change la valeur d'un

paramètre, il peut prévenir tous les processus concernés.

Serveur d'encodage

Site Web

SUB : abonnés au sujet « changementd'un paramètre »

Admin

{'settings': 'debug', 'oldValue' : false, 'newValue' : true}

Montrez-moi le code !

Même exemple que pour RPC, mais cette fois, on peut ouvrir index.html dans plusieurs tabs à la

fois.

Résultat attendu Index.html

button.html

PUB

Callback

(A SUB préalablement)

Si on ouvre 10 tabs avecindex.html, les 10 vont réagir. Mais button.html ne peut pas récupérer de valeuren retour.

index.html<!DOCTYPE html><html> <head> <script src="https://autobahn.s3.amazonaws.com/autobahnjs/latest/autobahn.min.jgz" type="text/javascript"></script></head><body><p id="baby">J'attends des nouvelles de fascinatingSubject</p></body><script>// Connexion au serveur de test WAMP.var connection = new autobahn.Connection({ url: 'wss://demo.crossbar.io/ws', realm: 'realm1'});

// Lancer ce code une fois que la connexion est réussie.connection.onopen = function (session) { // On déclare que cette fonction est appelée si il y a des nouvelles // à propos de ce sujet session.subscribe('fascinatingSubject', function(message){ // On change le contenu de la page. document.getElementById('baby').innerHTML = message // Pas de valeur de retour, le PUB/SUB est à sens unique });};

// Ouvrir la connexion.connection.open();</script></html>

button.html<!DOCTYPE html><html> <head> <script src="https://autobahn.s3.amazonaws.com/autobahnjs/latest/autobahn.min.jgz" type="text/javascript"></script></head><body><p><button onClick='sayIt()'>Say It, bobby !</button></p></body><script>// Connexion au serveur de test WAMP.var connection = new autobahn.Connection({ url: 'wss://demo.crossbar.io/ws', realm: 'realm1'});

// Lancer ce code une fois que la connexion est réussie.connection.onopen = function(session) { sayIt = function(){ /* Publication sur le sujet fascinatingSubject */ session.publish("fascinatingSubject", ['Amazing !']); // Pas de retour de valeur puisqu'on ne sait pas quels // clients vont recevoir le message }};

// Ouvrir la connexion.connection.open();</script></html>

La stack complète

Que faire de tout ça ?

● Des apps Web complètes. WAMP est un bon compagnon de frameworks comme AngularJS et remplace AJAX ou les websockets à la main pour une mise à jour en temps réel.

● Des grappes d'objets connectés (IoT, Rasberry PI, Arduino…) : remplace MQTT.

● Des microservices : authentification, logging, encodage video. Remplace AMQP et ZeroMQ.

● Des jeux vidéos.● Des applications collaboratives (à la Google Doc).● Des apps Androids ou iOS natives.

A propos de crossbar.io

● Crossbar est un routeur WAMP complet. Sans routeur, les clients ne peuvent se parler.

● Il doit être accessible via websocket.● Il peut gérer le cycle de vie des clients.● Il peut aussi gérer le cycle de vie de processus non

WAMP : c'est un gestionnaire de processus complet (comme supervisord) afin de faciliter les architectures à base de plusieurs micro-services.

● Il intègre même un serveur Web si nécessaire.

Où est le piège ?

● Technologie encore jeune. WAMP V1 vient d'être déprécié en faveur de WAMP 2.

● Des outils qui restent à créer : authentification utilisateur, debugage avancé...

● Obligation d'être asynchrone : pour le moment incompatible avec WSGI (et donc Django). Un bridge est en projet.

● Une doc toujours en évolution (mais je viens d'être embauché pour ça).

Does it blend ?

En stressant un peu sa stack WAMP, on peut :

● Envoyer 1,000 PubSub/sec de 32+ bytes vers 1,000 abonnés pour une latence moyenne de 25 ms avec une charge CPU de 65%.

ou● Envoyer 6,000 RPC/sec, avec une latence moyenne de 400 ms.

ou● Servir 6,000 clients, avec une latence moyenne de 850ms.

Does it blend ?

En stressant un peu sa stack WAMP, on peut :

● Envoyer 1,000 PubSub/sec de 32+ bytes vers 1,000 abonnés pour une latence moyenne de 25 ms avec une charge CPU de 65%.

ou● Envoyer 6,000 RPC/sec, avec une latence moyenne de 400 ms.

ou● Servir 6,000 clients, avec une latence moyenne de 850ms.

Sur un Rasberry Pi :)

Par où commencer ?

Choisissez votre langage, et écrivez un petit client à l'aide du serveur de démo :

http://crossbar.io/docs/Choose-your-Weapon/