AnyMQ, Hippie, and the real-time web
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

AnyMQ, Hippie, and the real-time web

on

  • 3,427 views

 

Statistics

Views

Total Views
3,427
Views on SlideShare
2,959
Embed Views
468

Actions

Likes
1
Downloads
24
Comments
0

3 Embeds 468

http://dave.thehorners.com 465
http://translate.googleusercontent.com 2
http://www.techgig.com 1

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • most of the time i am cooking <br />
  • <br /> <br />
  • <br /> <br />
  • sometimes i wrote some code <br />
  • things i ve been playing with <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • multiple event loop <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • time out handler supported <br />
  • time out handler supported <br />
  • time out handler supported <br />
  • time out handler supported <br />
  • time out handler supported <br />
  • time out handler supported <br />
  • time out handler supported <br />
  • time out handler supported <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • please help writing mq bindings <br />
  • <br /> <br />
  • 2006, coined by Alex Russell <br /> Server push for real time notification <br />
  • 2006, coined by Alex Russell <br /> Server push for real time notification <br />
  • <br /> <br />
  • multi-part XHR <br /> forever iframe, with script callbacks <br /> spinning &#x201C;loading&#x201D; indicator for FF and IE <br /> number of connections limits <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • only websockets and mxhr? <br />
  • maybe hippies should be more relaxed <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />
  • <br /> <br />

AnyMQ, Hippie, and the real-time web Presentation Transcript

  • 1. AnyMQ, Hippie and the real-time web YAPC::Asia 2010 Tokyo Chia-liang Kao clkao@clkao.org
  • 2. clkao
  • 3. • PSGI, Plack • AnyEvent, AnyMQ, AMQP • Server-push, comet • Websocket • Web::Hippie, Web::Hippie:Pipe
  • 4. • PSGI, Plack • AnyEvent, AnyMQ, AMQP • Server-push, comet • Websocket • Web::Hippie, Web::Hippie::Pipe
  • 5. Plack: Web
  • 6. PSGI
  • 7. $env [ '200', [ 'Content-Type' => 'text/plain' ], [ "Hello World" ], ]
  • 8. $env->{PATH_INFO} $env [ '200', [ 'Content-Type' => 'text/plain' ], [ "Hello World" ], ]
  • 9. $env->{PATH_INFO} Plack::Request->new($env)->path_info $env [ '200', [ 'Content-Type' => 'text/plain' ], [ "Hello World" ], ]
  • 10. $env Streaming Interface sub { my $responder = shift; my $writer = $responder->([ '200', [ 'Content-Type' => 'text/plain' ]); # later, of in a callback $writer->write(“Hello world!”); $writer->close(); }
  • 11. $env Streaming Interface(Cont.) sub { my $responder = shift; my $writer = $responder->([ '200', [ 'Content-Type' => 'text/plain' ]); # later, of in a callback my $w; $w = AnyEvent->timer(after => 3, cb => sub { $writer->write(“Hello world!”); $writer->close(); }); }
  • 12. CGI.pm ! ☠! ☠! ☠
  • 13. • PSGI, Plack • AnyEvent, AnyMQ, AMQP • Server-push, comet • Websocket • Web::Hippie, Web::Hippie::Pipe
  • 14. AnyEvent • •
  • 15. AnyEvent • • use AnyEvent::HTTP; http_get "http://yapc.asia/", sub { print $_[1] }; # do something else
  • 16. POE
  • 17. sub POE::Kernel::ASSERT_DEFAULT () { 1 } use HTTP::Request; use POE qw(Component::Client::HTTP); POE::Component::Client::HTTP->spawn(   Alias => 'ua', # defaults to 'weeble'   Timeout => 20, # defaults to 180 seconds ); POE::Session->create(   inline_states => {     _start => sub {       POE::Kernel->post(         'ua', # posts to the 'ua' alias         'request', # posts to ua's 'request' state         'response', # which of our states will receive the response         HTTP::Request->new(GET => “http://osdc.tw”),       );     },     _stop => sub {},     response => &response_handler,   }, ); POE::Kernel->run(); exit; sub response_handler {   my ($request_packet, $response_packet) = @_[ARG0, ARG1];   my $request_object = $request_packet->[0];   my $response_object = $response_packet->[0]; }
  • 18. ☹
  • 19. use AnyEvent::HTTP; http_get "http://yapc.asia/", sub { print $_[1] }; ☺
  • 20. AnyEvent::* AnyEvent-AIO AnyEvent-APNS AnyEvent-Atom-Stream AnyEvent-BDB AnyEvent- Beanstalk AnyEvent-Connection AnyEvent-CouchDB AnyEvent-DBI AnyEvent-DBI- Abstract AnyEvent-EditText AnyEvent-FCGI AnyEvent-FCP AnyEvent-FIFO AnyEvent- FastPing AnyEvent-Feed AnyEvent-Filesys-Notify AnyEvent-FriendFeed-Realtime AnyEvent-GPSD AnyEvent-Gearman AnyEvent-Gearman AnyEvent-Gmail-Feed AnyEvent-HTTP AnyEvent-HTTP-MXHR AnyEvent-HTTPD AnyEvent-I3 AnyEvent-IRC AnyEvent-JSONRPC-Lite AnyEvent-Kanye AnyEvent-MP AnyEvent-MPRPC AnyEvent- Memcached AnyEvent-Mojo AnyEvent-Monitor-CPU AnyEvent-Pcap AnyEvent-Plurk AnyEvent-Postfix-Logs AnyEvent-RTPG AnyEvent-Redis AnyEvent-RetryTimer AnyEvent-ReverseHTTP AnyEvent-Riak AnyEvent-Run AnyEvent-SCGI AnyEvent-SMTP AnyEvent-SNMP AnyEvent-Subprocess AnyEvent-Superfeedr AnyEvent-Twitter AnyEvent-Twitter-Stream AnyEvent-Watchdog AnyEvent-Worker AnyEvent-XMLRPC AnyEvent-XMPP AnyEvent-mDNS
  • 21. AnyMQ
  • 22. AnyMQ • Tatsumaki::MessageQueue
  • 23. AnyMQ • Tatsumaki::MessageQueue
  • 24. AnyMQ • Tatsumaki::MessageQueue
  • 25. AnyMQ • Tatsumaki::MessageQueue •
  • 26. AnyMQ • Tatsumaki::MessageQueue • • Moose
  • 27. AnyMQ • Tatsumaki::MessageQueue • • Moose
  • 28. AnyMQ • Tatsumaki::MessageQueue • • Moose
  • 29. AnyMQ my $bus = AnyMQ->new; my $topic = $bus->topic("Foo"); my $sub = $bus->new_listener($topic); $sub->poll(sub { my $msg = shift; }) $topic->publish($msg)
  • 30. AnyMQ with AMQP my $bus = AnyMQ->new_with_traits ( traits => [ ‘AMQP’], # host => ..., port => ..); my $topic = $bus->topic("Foo"); my $sub = $bus->new_listener($topic); $sub->poll(sub { my $msg = shift; }) $topic->publish($msg)
  • 31. AnyMQ with AMQP
  • 32. AnyMQ with AMQP my $bus = AnyMQ->new_with_traits my $bus = AnyMQ->new_with_traits ( traits => [ ‘AMQP’], ( traits => [ ‘AMQP’], # host => ..., port => ..); # host => ..., port => ..); my $topic = $bus->topic("Foo"); my $topic = $bus->topic("Foo"); my $sub = $bus->new_listener($topic); my $sub = $bus->new_listener($topic); $sub->poll(sub { my $msg = shift; }) $sub->poll(sub { my $msg = shift; }) $topic->publish($msg) $topic->publish($msg) my $bus = AnyMQ->new_with_traits my $bus = AnyMQ->new_with_traits ( traits => [ ‘AMQP’], ( traits => [ ‘AMQP’], # host => ..., port => ..); # host => ..., port => ..); my $topic = $bus->topic("Foo"); my $topic = $bus->topic("Foo"); my $sub = $bus->new_listener($topic); my $sub = $bus->new_listener($topic); $sub->poll(sub { my $msg = shift; }) $sub->poll(sub { my $msg = shift; }) $topic->publish($msg) $topic->publish($msg)
  • 33. AnyMQ with AMQP my $bus = AnyMQ->new_with_traits my $bus = AnyMQ->new_with_traits ( traits => [ ‘AMQP’], ( traits => [ ‘AMQP’], # host => ..., port => ..); # host => ..., port => ..); my $topic = $bus->topic("Foo"); my $topic = $bus->topic("Foo"); my $sub = $bus->new_listener($topic); my $sub = $bus->new_listener($topic); $sub->poll(sub { my $msg = shift; }) $sub->poll(sub { my $msg = shift; }) $topic->publish($msg) $topic->publish($msg) AMQP Server my $bus = AnyMQ->new_with_traits my $bus = AnyMQ->new_with_traits ( traits => [ ‘AMQP’], ( traits => [ ‘AMQP’], # host => ..., port => ..); # host => ..., port => ..); my $topic = $bus->topic("Foo"); my $topic = $bus->topic("Foo"); my $sub = $bus->new_listener($topic); my $sub = $bus->new_listener($topic); $sub->poll(sub { my $msg = shift; }) $sub->poll(sub { my $msg = shift; }) $topic->publish($msg) $topic->publish($msg)
  • 34. !
  • 35. • PSGI, Plack • AnyEvent, AnyMQ, AMQP • Server-push, comet • Websocket • Web::Hippie, Web::Hippie::Pipe
  • 36. Comet -
  • 37. Comet The word comet came to English by way of the Latin word cometes. This word, in turn, came from the Greek word κόμη, which means "hair of the head". The Greek scientist and philosopher Aristotlefirst used the derived form of κόμη, κομήτης, to describe what he saw as "stars with hair." Theastronomical symbol for comets is (☄), consisting of a small disc with three hairlike extensions. -
  • 38. Comet The word comet came to English by way of the Latin word cometes. This word, in turn, came from the Greek word κόμη, which means "hair of the head". The Greek scientist and philosopher Aristotlefirst used the derived form of κόμη, κομήτης, to describe what he saw as "stars with hair." Theastronomical symbol for comets is (☄), consisting of a small disc with three hairlike extensions. - • 2006 •
  • 39. • gmail • twitter • facebook updates
  • 40. ! • XHR • iframe • FF IE •
  • 41. • PSGI, Plack • AnyEvent, AnyMQ, AMQP • Server-push, comet • Websocket • Web::Hippie, Web::Hippie::Pipe
  • 42. HTML5 Standard
  • 43. ws://example.com wss://example.com
  • 44. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U
  • 45. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U
  • 46. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U
  • 47. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U
  • 48. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U
  • 49. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U Response: HTTP/1.1 101 WebSocket Protocol Handshake Upgrade: WebSocket Connection: Upgrade Sec-WebSocket-Origin: http://example.com Sec-WebSocket-Location: ws://example.com/demo Sec-WebSocket-Protocol: sample 8jKS'y:G*Co,Wxa-
  • 50. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U Response: HTTP/1.1 101 WebSocket Protocol Handshake Upgrade: WebSocket Connection: Upgrade Sec-WebSocket-Origin: http://example.com Sec-WebSocket-Location: ws://example.com/demo Sec-WebSocket-Protocol: sample 8jKS'y:G*Co,Wxa-
  • 51. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U Response: HTTP/1.1 101 WebSocket Protocol Handshake Upgrade: WebSocket Connection: Upgrade Sec-WebSocket-Origin: http://example.com Sec-WebSocket-Location: ws://example.com/demo Sec-WebSocket-Protocol: sample 8jKS'y:G*Co,Wxa-
  • 52. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com New in draft#76 ^n:ds[4U Response: HTTP/1.1 101 WebSocket Protocol Handshake Upgrade: WebSocket Connection: Upgrade Sec-WebSocket-Origin: http://example.com Sec-WebSocket-Location: ws://example.com/demo Sec-WebSocket-Protocol: sample 8jKS'y:G*Co,Wxa-
  • 53. my @keys = map { my $k = $env>{'HTTP_SEC_WEBSOCKET_KEY'.$_}; join('', $k =~ m/d/g) / scalar @{[$k =~ m/ /g]}; } (1,2); md5(pack('NN', @keys) . $key3);
  • 54. Messages surrounded by x{00} and x{ff}
  • 55. Websockets API
  • 56. Websockets API ws = new WebSocket("ws://foo.com:5000”)); ws.onopen = function(ev) { ... } ws.onmessage = function(ev) { ... } ws.onclose = function(ev) { ... } ws.onerror = function(ev) { ... } ws.send(....);
  • 57. Websockets API ws = new WebSocket("ws://foo.com:5000”)); ws.onopen = function(ev) { ... } ws.onmessage = function(ev) { ... } ws.onclose = function(ev) { ... } ws.onerror = function(ev) { ... } ws.send(....); Can accept cross-site connection with Origin and Sec- WebSocket-Origin headers
  • 58. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U
  • 59. Request: GET /demo HTTP/1.1 Host: example.com Connection: Upgrade Sec-WebSocket-Key2: 12998 5 Y3 1 .P00 Sec-WebSocket-Protocol: sample Upgrade: WebSocket Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5 Origin: http://example.com ^n:ds[4U Response: HTTP/1.1 101 WebSocket Protocol Handshake Upgrade: WebSocket Connection: Upgrade Sec-WebSocket-Origin: http://example.com Sec-WebSocket-Location: ws://example.com/demo Sec-WebSocket-Protocol: sample 8jKS'y:G*Co,Wxa-
  • 60. • PSGI, Plack • AnyEvent, AnyMQ, AMQP • Server-push, comet • Websocket • Web::Hippie, Web::Hippie::Pipe
  • 61. Web
  • 62. • : Websocket, MXHR
  • 63. • : Websocket, MXHR enable "+Web::Hippie"; sub { my $env = shift; my $args = $env->{'hippie.args'}; my $handle = $env->{'hippie.handle'}; # Your handler based on PATH_INFO: # /init, /error, /message }
  • 64. • : Websocket, MXHR Just a normal PSGI-app! enable "+Web::Hippie"; sub { my $env = shift; my $args = $env->{'hippie.args'}; my $handle = $env->{'hippie.handle'}; # Your handler based on PATH_INFO: # /init, /error, /message }
  • 65. • : Websocket, MXHR mount it to /_hippie enable "+Web::Hippie"; sub { my $env = shift; my $args = $env->{'hippie.args'}; my $handle = $env->{'hippie.handle'}; # Your handler based on PATH_INFO: # /init, /error, /message }
  • 66. Must use PSGI servers supporting psgi.nonblocking:
  • 67. Must use PSGI servers supporting psgi.nonblocking: twiggy feersum
  • 68. Websocket mxhr ?
  • 69. ?
  • 70. …
  • 71. Hippie::Pipe +
  • 72. Hippie::Pipe • : Websocket MXHR poll AnyMQ support
  • 73. Hippie::Pipe • : Websocket MXHR poll AnyMQ support enable "+Web::Hippie"; enable "+Web::Hippie::Pipe", bus => AnyMQ->new; sub { my $env = shift; my $sub = $env->{'hippie.listener'}; my $bus = $env->{'hippie.bus'}; my $msg = $env->{'hippie.message'}; # Your handler based on PATH_INFO: # /new_listener, /error, /message }
  • 74. Hippie::Pipe(Cont.)
  • 75. Hippie::Pipe(Cont.) my $topic = $bus->topic(‘news’); # my $sub = $env->{'hippie.listener'}; if ($env->{PATH_INFO} eq ‘/new_listener’) { $sub->subscribe($topic); } # $topic->publish({type => ‘news.yapc’, message => ‘something’});
  • 76. Hippie::Pipe(Cont.) my $topic = $bus->topic(‘news’); # my $sub = $env->{'hippie.listener'}; if ($env->{PATH_INFO} eq ‘/new_listener’) { $sub->subscribe($topic); } # $topic->publish({type => ‘news.yapc’, message => ‘something’});
  • 77. Hippie::Pipe(Cont.) my $topic = $bus->topic(‘news’); # my $sub = $env->{'hippie.listener'}; if ($env->{PATH_INFO} eq ‘/new_listener’) { $sub->subscribe($topic); } # $topic->publish({type => ‘news.yapc’, message => ‘something’});
  • 78. hpipe = new Hippie.Pipe(); $(hpipe) .bind(“ready”, function() { hpipe.send({type: ‘news.viewer’, ident: ‘clkao’}) }) .bind(“disconnected”, function() {}) .bind(“message.news.yapc”, function(e, data) {}); hpipe.init();
  • 79. hpipe = new Hippie.Pipe(); $(hpipe) .bind(“ready”, function() { hpipe.send({type: ‘news.viewer’, ident: ‘clkao’}) }) .bind(“disconnected”, function() {}) .bind(“message.news.yapc”, function(e, data) {}); hpipe.init();
  • 80. hpipe = new Hippie.Pipe(); $(hpipe) .bind(“ready”, function() { hpipe.send hpipe.send({type: ‘news.viewer’, ident: ‘clkao’}) }) .bind(“disconnected”, function() {}) .bind(“message.news.yapc”, function(e, data) {}); hpipe.init();
  • 81. hpipe = new Hippie.Pipe(); $(hpipe) .bind(“ready”, function() { hpipe.send hpipe.send({type: ‘news.viewer’, ident: ‘clkao’}) }) .bind(“disconnected”, function() {}) .bind(“message.news.yapc”, function(e, data) {}); hpipe.init();
  • 82. Hippie::Pipe(Cont.)
  • 83. Hippie::Pipe(Cont.) # my $sub = $env->{'hippie.listener'}; # my $msg = $env->{'hippie.message'}; if ($env->{PATH_INFO} eq ‘/message’) { if ($msg->{type} eq ‘news.viewer’) { $topic->publish({type => ‘news.viewer’, user => $msg->{user}); } }
  • 84. Hippie::Pipe(Cont.) # my $sub = $env->{'hippie.listener'}; # my $msg = $env->{'hippie.message'}; if ($env->{PATH_INFO} eq ‘/message’) { if ($msg->{type} eq ‘news.viewer’) { $topic->publish({type => ‘news.viewer’, user => $msg->{user}); } }
  • 85. Hippie::Pipe(Cont.) # my $sub = $env->{'hippie.listener'}; # my $msg = $env->{'hippie.message'}; if ($env->{PATH_INFO} eq ‘/message’) { if ($msg->{type} eq ‘news.viewer’) { $topic->publish({type => ‘news.viewer’, user => $msg->{user}); } } # Client: # bind(“message.news.viewer”, function(){..})
  • 86. DEMO at Jesse’s Talk 12:00 today
  • 87. DEMO
  • 88. Thank you! special thanks to Ishigaki-san and Danjou-san for translations