Real time

1,264 views
1,192 views

Published on

Diapositivas correspondientes a la parte de Web en tiempo real, del curso de extensión universitaria "Cloud Computing. Desarrollo de Aplicaciones y Minería Web", celebrado en la Escuela Universitaria de Ingeniería Informática de Oviedo

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,264
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
0
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Real time

  1. 1. CLOUD COMPUTING. DESARROLLO DE APLICACIONESY MINERÍA WEB Programa de extensión universitariaUniversidad de Oviedo Miguel Fernández Fernández miguel@ThirdWay.es
  2. 2. Web enTiempo Real XMPP, Websockets, et al.
  3. 3. ¿Qué es XMPP? Extensible Messaging and Presence Protocol Envío de mensajes en tiempo real Codificados en XML Transportados sobreTCP y UDP (media) antesJabber http://xmpp.org
  4. 4. ¿Por qué XMPP? HTTP Half-duplex para la Web stateless
  5. 5. ¿Por qué XMPP? HTTP Half-duplex c s normal polling (AJAX) c s long polling (Comet) para la Web stateless
  6. 6. ¿Por qué XMPP? HTTP Half-duplex c s normal polling (AJAX) c s long polling (Comet) para la Web stateless XMPP Full-duplex stateful
  7. 7. ¿Por qué XMPP? HTTP Half-duplex c s normal polling (AJAX) c s long polling (Comet) para la Web stateless XMPP Full-duplex stateful c s conexión persistente
  8. 8. Arquitectura XMPP O’REILLY XMPP:The Definitive Guide
  9. 9. Arquitectura XMPP Web (HTTP) Mail (SMTP) XMPP
  10. 10. La red XMPP: Entidades Servidores Plugins Componentes Clientes
  11. 11. Servidores Enrutan mensajes Hablan con clientes y otros servidores FOSS: Ejabberd, Openfire,Tigase
  12. 12. Clientes Humanos y robots Protocolo cliente-servidor
  13. 13. 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
  14. 14. Plugins Mismo propósito que los componentes También tienen identidad y dirección No hay IPC mayor rendimiento
  15. 15. Direccionamiento en XMPP JIDs: almenos uno por cada entidad local@dom.ain/resource it@miinterprete.appspotchat.com/adium Bare JID Full JID
  16. 16. XMPP Stanzas <stream:stream> <iq type="get"> <query xmlns="jabber:iq:roster"/> </iq> <presence/> <message to="bar@otherside.com" from="foo@oneside.com/adium" type="chat"> <body>Tomamos algo?</body> </message> <presence type="unavailable"/> </stream:stream>
  17. 17. XMPP Stanzas <stream:stream> <iq type="get"> <query xmlns="jabber:iq:roster"/> </iq> <presence/> <message to="bar@otherside.com" from="foo@oneside.com/adium" type="chat"> <body>Tomamos algo?</body> </message> <presence type="unavailable"/> </stream:stream>
  18. 18. XMPP Stanzas <stream:stream> <iq type="get"> <query xmlns="jabber:iq:roster"/> </iq> <presence/> <message to="bar@otherside.com" from="foo@oneside.com/adium" type="chat"> <body>Tomamos algo?</body> </message> <presence type="unavailable"/> </stream:stream> Dame mis contactos
  19. 19. XMPP Stanzas <stream:stream> <iq type="get"> <query xmlns="jabber:iq:roster"/> </iq> <presence/> <message to="bar@otherside.com" from="foo@oneside.com/adium" type="chat"> <body>Tomamos algo?</body> </message> <presence type="unavailable"/> </stream:stream> Dame mis contactos Estoy online
  20. 20. XMPP Stanzas <stream:stream> <iq type="get"> <query xmlns="jabber:iq:roster"/> </iq> <presence/> <message to="bar@otherside.com" from="foo@oneside.com/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
  21. 21. XMPP Stanzas <stream:stream> <iq type="get"> <query xmlns="jabber:iq:roster"/> </iq> <presence/> <message to="bar@otherside.com" from="foo@oneside.com/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
  22. 22. Tiempo real en La Web
  23. 23. Acercando XMPP a la Web Pre HTML 5 Comunicación basada en HTTP Bidirectional-Streams over synchronous HTTP AJAX & Long Polling
  24. 24. 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
  25. 25. 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 OK Content-Type: text/xml; charset=utf-8 Content-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>
  26. 26. HTML5 Websockets HTML 5 WebSockets To enableWeb applications to maintain bidirectional communications with server-side processes, this specification introduces theWebSocket interface. Gecko 2.0b4 (24/08/2010) (Firefox 4 Nighties) Webkit 333 (Safari 4, Chrome >4)Soportado en:
  27. 27. HTML5 Websockets HTML 5 WebSockets To enableWeb applications to maintain bidirectional communications with server-side processes, this specification introduces theWebSocket interface. Gecko 2.0b4 (24/08/2010) (Firefox 4 Nighties) Webkit 333 (Safari 4, Chrome >4)Soportado en: c s conexión persistente
  28. 28. 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
  29. 29. Web en tiempo real con Websockets
  30. 30. 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)
  31. 31. 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>
  32. 32. 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>
  33. 33. 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>
  34. 34. 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>
  35. 35. 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>
  36. 36. 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>
  37. 37. 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>
  38. 38. 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
  39. 39. Multichat en 23LOC require '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 end end
  40. 40. 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
  41. 41. Bilbiografía
  42. 42. Gracias
  43. 43. CLOUD COMPUTING. DESARROLLO DE APLICACIONESY MINERÍA WEB Programa de extensión universitariaUniversidad de Oviedo Miguel Fernández Fernández miguel@ThirdWay.es

×