real-time web

44
CLOUD COMPUTING. DESARROLLO DE APLICACIONES Y MINERÍA WEB Miguel Fernández Fernández [email protected] Programa de extensión universitaria Universidad de Oviedo

Upload: miguel-fernandez

Post on 22-May-2015

1.195 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Real-time web

CLOUD COMPUTING.DESARROLLO DE APLICACIONES Y

MINERÍA WEB

Miguel Fernández Fernández [email protected]

Programa de extensión universitariaUniversidad de Oviedo

Page 2: Real-time web

Web en Tiempo RealXMPP, Websockets, et al.

Page 3: Real-time web

¿Qué es XMPP?

Extensible Messaging and Presence Protocol

Envío de mensajes en tiempo real

Codificados en XML

Transportados sobre TCP y UDP (media)

antesJabber

http://xmpp.org

Page 4: Real-time web

¿Por qué XMPP?HTTP

Half-duplex

para la Web

stateless

Page 5: Real-time web

¿Por qué XMPP?HTTP

Half-duplex

c

snormal polling (AJAX)

c

slong polling (Comet)

para la Web

stateless

Page 6: Real-time web

¿Por qué XMPP?HTTP

Half-duplex

c

snormal polling (AJAX)

c

slong polling (Comet)

para la Web

stateless

XMPP

Full-duplex

stateful

Page 7: Real-time web

¿Por qué XMPP?HTTP

Half-duplex

c

snormal polling (AJAX)

c

slong polling (Comet)

para la Web

stateless

XMPP

Full-duplex

stateful

c

sconexión persistente

Page 8: Real-time web

Arquitectura XMPP

O’REILLY XMPP: The Definitive Guide

Page 9: Real-time web

Arquitectura XMPP

Web (HTTP) Mail (SMTP)

XMPP

Page 10: Real-time web

La red XMPP: Entidades

Servidores

Plugins

Componentes

Clientes

Page 11: Real-time web

Servidores

Enrutan mensajes

Hablan con clientes y otros servidores

FOSS: Ejabberd, Openfire, Tigase

Page 12: Real-time web

Clientes

Humanos y robots

Protocolo cliente-servidor

Page 13: Real-time web

Componentes

Extienden la funcionalidad del servidor

Tienen su propia identidad y dirección

Se ejecutan fuera del mismo

Se comunican con un protocolo específico

Ejemplo típico: Multichat

Page 14: Real-time web

Plugins

Mismo propósito que los componentes

También tienen identidad y dirección

No hay IPC mayor rendimiento

Page 16: Real-time web

XMPP Stanzas

<stream:stream>

<iq type="get"> <query xmlns="jabber:iq:roster"/> </iq>

<presence/>

<message to="[email protected]" from="[email protected]/adium" type="chat"> <body>Tomamos algo?</body> </message>

<presence type="unavailable"/>

</stream:stream>

Page 17: Real-time web

XMPP Stanzas

<stream:stream>

<iq type="get"> <query xmlns="jabber:iq:roster"/> </iq>

<presence/>

<message to="[email protected]" from="[email protected]/adium" type="chat"> <body>Tomamos algo?</body> </message>

<presence type="unavailable"/>

</stream:stream>

Page 18: Real-time web

XMPP Stanzas

<stream:stream>

<iq type="get"> <query xmlns="jabber:iq:roster"/> </iq>

<presence/>

<message to="[email protected]" from="[email protected]/adium" type="chat"> <body>Tomamos algo?</body> </message>

<presence type="unavailable"/>

</stream:stream>

Dame mis contactos

Page 19: Real-time web

XMPP Stanzas

<stream:stream>

<iq type="get"> <query xmlns="jabber:iq:roster"/> </iq>

<presence/>

<message to="[email protected]" from="[email protected]/adium" type="chat"> <body>Tomamos algo?</body> </message>

<presence type="unavailable"/>

</stream:stream>

Dame mis contactos

Estoy online

Page 20: Real-time web

XMPP Stanzas

<stream:stream>

<iq type="get"> <query xmlns="jabber:iq:roster"/> </iq>

<presence/>

<message to="[email protected]" from="[email protected]/adium" type="chat"> <body>Tomamos algo?</body> </message>

<presence type="unavailable"/>

</stream:stream>

Dame mis contactos

Estoy online

Dile a bar que si tomamos algo

Page 21: Real-time web

XMPP Stanzas

<stream:stream>

<iq type="get"> <query xmlns="jabber:iq:roster"/> </iq>

<presence/>

<message to="[email protected]" from="[email protected]/adium" type="chat"> <body>Tomamos algo?</body> </message>

<presence type="unavailable"/>

</stream:stream>

Dame mis contactos

Estoy online

Dile a bar que si tomamos algoYa no estoy disponible

Page 22: Real-time web

Tiempo real en La Web

Page 23: Real-time web

Acercando XMPP a la Web

Pre HTML 5

Comunicación basada en HTTP

Bidirectional-Streams over synchronous HTTP

AJAX & Long Polling

Page 24: Real-time web

AJAX & Long Polling

setInterval(function(){ // pedimos cada 500 milisegundos esperando cambio $.ajax({ url: '/my/page', success: function(data){} });}, 500);

function load(){ $.ajax({ url: '/my/page', success: function(){ // abrimos la conexión durante 20 segundos }, complete: load, timeout: 20000 });}

AJAX (muestreo frecuente) Comet (Long Polling)

Latencia (200ms/petición)

Muchas peticiones no recogeran cambios

Se genera mucho tráfico

Reducción dramática de latencia

Mucho más eficiente

Page 25: Real-time web

BOSH, XMPP sobre HTTP

http://xmpp.org/extensions/xep-0206.html

Flujos bidireccionales sobre HTTP síncrono

Usa pares de petición-respuesta para simular

Requiere de un proxy que dirija los stanzas al servidor XMPP

HTTP/1.1 200 OKContent-Type: text/xml; charset=utf-8Content-Length: 483

<body xmpp:version='1.0' authid='ServerStreamID' xmlns='http://jabber.org/protocol/httpbind' xmlns:xmpp='urn:xmpp:xbosh' xmlns:stream='http://etherx.jabber.org/streams'> <stream:features> <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <mechanism>SCRAM-SHA-1</mechanism> <mechanism>PLAIN</mechanism> </mechanisms> </stream:features></body>

Page 26: Real-time web

HTML5 WebsocketsHTML 5

WebSocketsTo enable Web applications to maintain bidirectional

communications with server-side processes, this specification introduces the WebSocket interface.

Gecko 2.0b4 (24/08/2010) (Firefox 4 Nighties)Webkit 333 (Safari 4, Chrome >4)Soportado en:

Page 27: Real-time web

HTML5 WebsocketsHTML 5

WebSocketsTo enable Web applications to maintain bidirectional

communications with server-side processes, this specification introduces the WebSocket interface.

Gecko 2.0b4 (24/08/2010) (Firefox 4 Nighties)Webkit 333 (Safari 4, Chrome >4)Soportado en:

c

sconexión persistente

Page 28: Real-time web

El contrato Websocket[Constructor(in DOMString url, in optional DOMString protocols)][Constructor(in DOMString url, in optional DOMString[] protocols)]interface WebSocket { readonly attribute DOMString url;

// ready state const unsigned short CONNECTING = 0; const unsigned short OPEN = 1; const unsigned short CLOSING = 2; const unsigned short CLOSED = 3; readonly attribute unsigned short readyState; readonly attribute unsigned long bufferedAmount;

// networking attribute Function onopen; attribute Function onmessage; attribute Function onerror; attribute Function onclose; readonly attribute DOMString protocol; void send(in DOMString data); void close();};WebSocket implements EventTarget;

estado de la conexión

Recepción de eventos

Envío de mensajes

ws://services.com/service

Page 29: Real-time web

Web en tiempo real con Websockets

Page 30: Real-time web

Event Machine

http://rubyeventmachine.com/

Framework I/O dirigida por eventos

Corre sobre ruby

à-la node.js (javascript) y twisted (python)

Implementa el patrón Reactor

Muy útil para crear aplicaciones servidor

eventmachine (0.12.10)eventmachine-websocket (0.1.0)

Page 31: Real-time web

Nuestro cliente<html> <head> <script src='jquery.min.js'></script> <script> function WebSocketAdapter(url){ this.ws=new WebSocket(url); this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");}; this.ws.onclose = function() { alert("socket cerrado"); }; this.ws.onopen = function() { alert("conectado..."); }; this.send=function(msg) {this.ws.send(msg);} } var ws; $(document).ready(function(){ ws=new WebSocketAdapter("ws://localhost:8080/"); }); </script> </head> <body> <form> Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input> <input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/> </form> <div id="msg"></div> </body></html>

Page 32: Real-time web

Nuestro cliente<html> <head> <script src='jquery.min.js'></script> <script> function WebSocketAdapter(url){ this.ws=new WebSocket(url); this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");}; this.ws.onclose = function() { alert("socket cerrado"); }; this.ws.onopen = function() { alert("conectado..."); }; this.send=function(msg) {this.ws.send(msg);} } var ws; $(document).ready(function(){ ws=new WebSocketAdapter("ws://localhost:8080/"); }); </script> </head> <body> <form> Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input> <input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/> </form> <div id="msg"></div> </body></html>

Page 33: Real-time web

Nuestro cliente<html> <head> <script src='jquery.min.js'></script> <script> function WebSocketAdapter(url){ this.ws=new WebSocket(url); this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");}; this.ws.onclose = function() { alert("socket cerrado"); }; this.ws.onopen = function() { alert("conectado..."); }; this.send=function(msg) {this.ws.send(msg);} } var ws; $(document).ready(function(){ ws=new WebSocketAdapter("ws://localhost:8080/"); }); </script> </head> <body> <form> Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input> <input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/> </form> <div id="msg"></div> </body></html>

Page 34: Real-time web

Nuestro cliente<html> <head> <script src='jquery.min.js'></script> <script> function WebSocketAdapter(url){ this.ws=new WebSocket(url); this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");}; this.ws.onclose = function() { alert("socket cerrado"); }; this.ws.onopen = function() { alert("conectado..."); }; this.send=function(msg) {this.ws.send(msg);} } var ws; $(document).ready(function(){ ws=new WebSocketAdapter("ws://localhost:8080/"); }); </script> </head> <body> <form> Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input> <input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/> </form> <div id="msg"></div> </body></html>

Page 35: Real-time web

Nuestro cliente<html> <head> <script src='jquery.min.js'></script> <script> function WebSocketAdapter(url){ this.ws=new WebSocket(url); this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");}; this.ws.onclose = function() { alert("socket cerrado"); }; this.ws.onopen = function() { alert("conectado..."); }; this.send=function(msg) {this.ws.send(msg);} } var ws; $(document).ready(function(){ ws=new WebSocketAdapter("ws://localhost:8080/"); }); </script> </head> <body> <form> Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input> <input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/> </form> <div id="msg"></div> </body></html>

Page 36: Real-time web

Nuestro cliente<html> <head> <script src='jquery.min.js'></script> <script> function WebSocketAdapter(url){ this.ws=new WebSocket(url); this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");}; this.ws.onclose = function() { alert("socket cerrado"); }; this.ws.onopen = function() { alert("conectado..."); }; this.send=function(msg) {this.ws.send(msg);} } var ws; $(document).ready(function(){ ws=new WebSocketAdapter("ws://localhost:8080/"); }); </script> </head> <body> <form> Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input> <input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/> </form> <div id="msg"></div> </body></html>

Page 37: Real-time web

Nuestro cliente<html> <head> <script src='jquery.min.js'></script> <script> function WebSocketAdapter(url){ this.ws=new WebSocket(url); this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");}; this.ws.onclose = function() { alert("socket cerrado"); }; this.ws.onopen = function() { alert("conectado..."); }; this.send=function(msg) {this.ws.send(msg);} } var ws; $(document).ready(function(){ ws=new WebSocketAdapter("ws://localhost:8080/"); }); </script> </head> <body> <form> Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input> <input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/> </form> <div id="msg"></div> </body></html>

Page 38: Real-time web

Echo (single client)

require 'rubygems'require 'eventmachine-websocket'

EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080) do |con| con.on_open { con.send "Cliente conectado"} con.on_message { |msg| con.send msg.reverse } con.on_close { puts "Cliente desconectado" }end

Page 39: Real-time web

Multichat en 23LOCrequire 'rubygems'require 'eventmachine-websocket'

connections=[]indexes={}

EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080) do |con|

con.on_open do indexes[con]=connections.size+1 con.send "<p class=\"highlight\">Eres el cliente #{indexes[con]}<p>" connections.each{ |c| c.send "<p class=\"highlight\">El cliente #{indexes[con]} ha entrado en la sala<p>" } connections << con end con.on_message do |msg| connections.each{ |c| c.send "<p><span class=\"cliente\">Cliente #{indexes[con]}:</span> #{msg}</p>" } end con.on_close do c.send "<p class=\"highlight\">Has abandonado la sala</p>" connections.delete con indexes.delete con endend

Page 40: Real-time web
Page 41: Real-time web

Conclusiones

• Hasta la aparición de HTML5, XMPP tenía unas expectativas muy altas como alternativa a Comet.

• Sin embargo, se han cancelado muchos servicios XMPP para el consumo de datos en tiempo real (Twitter firehose API)

•Websocket se presenta como una alternativa más simple y elegante para la implementación de servicios Web de tiempo real

• XMPP no pierde fuerza para mensajería instantánea

Page 42: Real-time web

Bilbiografía

Page 43: Real-time web

Gracias

Page 44: Real-time web

CLOUD COMPUTING.DESARROLLO DE APLICACIONES Y

MINERÍA WEB

Miguel Fernández Fernández [email protected]

Programa de extensión universitariaUniversidad de Oviedo