Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
CLOUD COMPUTING.
DESARROLLO DE APLICACIONESY
MINERÍA WEB
Programa de extensión universitariaUniversidad de Oviedo
Miguel F...
Web enTiempo Real
XMPP, Websockets, et al.
¿Qué es XMPP?
Extensible Messaging and Presence Protocol
Envío de mensajes en tiempo real
Codificados en XML
Transportados ...
¿Por qué XMPP?
HTTP
Half-duplex
para la Web
stateless
¿Por qué XMPP?
HTTP
Half-duplex
c
s
normal polling (AJAX)
c
s
long polling (Comet)
para la Web
stateless
¿Por qué XMPP?
HTTP
Half-duplex
c
s
normal polling (AJAX)
c
s
long polling (Comet)
para la Web
stateless
XMPP
Full-duplex
...
¿Por qué XMPP?
HTTP
Half-duplex
c
s
normal polling (AJAX)
c
s
long polling (Comet)
para la Web
stateless
XMPP
Full-duplex
...
Arquitectura XMPP
O’REILLY XMPP:The Definitive Guide
Arquitectura XMPP
Web (HTTP) Mail (SMTP)
XMPP
La red XMPP: Entidades
Servidores
Plugins
Componentes
Clientes
Servidores
Enrutan mensajes
Hablan con clientes y otros servidores
FOSS: Ejabberd, Openfire,Tigase
Clientes
Humanos y robots
Protocolo cliente-servidor
Componentes
Extienden la funcionalidad del servidor
Tienen su propia identidad y dirección
Se ejecutan fuera del mismo
Se ...
Plugins
Mismo propósito que los componentes
También tienen identidad y dirección
No hay IPC mayor rendimiento
Direccionamiento en XMPP
JIDs: almenos uno por cada entidad
local@dom.ain/resource
it@miinterprete.appspotchat.com/adium
B...
XMPP Stanzas
<stream:stream>
<iq type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
<presence/>
<message to="bar@othersid...
XMPP Stanzas
<stream:stream>
<iq type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
<presence/>
<message to="bar@othersid...
XMPP Stanzas
<stream:stream>
<iq type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
<presence/>
<message to="bar@othersid...
XMPP Stanzas
<stream:stream>
<iq type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
<presence/>
<message to="bar@othersid...
XMPP Stanzas
<stream:stream>
<iq type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
<presence/>
<message to="bar@othersid...
XMPP Stanzas
<stream:stream>
<iq type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
<presence/>
<message to="bar@othersid...
Tiempo real en La Web
Acercando XMPP a la Web
Pre HTML 5
Comunicación basada en HTTP
Bidirectional-Streams over
synchronous HTTP
AJAX & Long Pol...
AJAX & Long Polling
setInterval(function(){
// pedimos cada 500 milisegundos esperando cambio
$.ajax({ url: '/my/page', su...
BOSH, XMPP sobre HTTP
http://xmpp.org/extensions/xep-0206.html
Flujos bidireccionales sobre HTTP síncrono
Usa pares de pet...
HTML5 Websockets
HTML 5
WebSockets
To enableWeb applications to maintain bidirectional
communications with server-side pro...
HTML5 Websockets
HTML 5
WebSockets
To enableWeb applications to maintain bidirectional
communications with server-side pro...
El contrato Websocket
[Constructor(in DOMString url, in optional DOMString protocols)]
[Constructor(in DOMString url, in o...
Web en tiempo real con
Websockets
Event Machine
http://rubyeventmachine.com/
Framework I/O dirigida por eventos
Corre sobre ruby
à-la node.js (javascript) y...
Nuestro cliente<html>
<head>
<script src='jquery.min.js'></script>
<script>
function WebSocketAdapter(url){
this.ws=new We...
Nuestro cliente<html>
<head>
<script src='jquery.min.js'></script>
<script>
function WebSocketAdapter(url){
this.ws=new We...
Nuestro cliente<html>
<head>
<script src='jquery.min.js'></script>
<script>
function WebSocketAdapter(url){
this.ws=new We...
Nuestro cliente<html>
<head>
<script src='jquery.min.js'></script>
<script>
function WebSocketAdapter(url){
this.ws=new We...
Nuestro cliente<html>
<head>
<script src='jquery.min.js'></script>
<script>
function WebSocketAdapter(url){
this.ws=new We...
Nuestro cliente<html>
<head>
<script src='jquery.min.js'></script>
<script>
function WebSocketAdapter(url){
this.ws=new We...
Nuestro cliente<html>
<head>
<script src='jquery.min.js'></script>
<script>
function WebSocketAdapter(url){
this.ws=new We...
Echo (single client)
require 'rubygems'
require 'eventmachine-websocket'
EventMachine::WebSocket.start(:host => "0.0.0.0",...
Multichat en 23LOC
require 'rubygems'
require 'eventmachine-websocket'
connections=[]
indexes={}
EventMachine::WebSocket.s...
Conclusiones
• Hasta la aparición de HTML5, XMPP tenía unas expectativas
muy altas como alternativa a Comet.
• Sin embargo...
Bilbiografía
Gracias
CLOUD COMPUTING.
DESARROLLO DE APLICACIONESY
MINERÍA WEB
Programa de extensión universitariaUniversidad de Oviedo
Miguel F...
Real time
Upcoming SlideShare
Loading in …5
×

Real time

1,398 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
  • Be the first to comment

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

×