SlideShare a Scribd company logo
1 of 199
Download to read offline
“ Genius is the gold in the mine; talent is
  the miner who works and brings it out. ”
 Lady Marguerite Blessington




                                        Donets Basin
                                        Coal Mine-Ukraine
“ Genius is the gold in the mine; talent is
  the miner who works and brings it out. ”
 Lady Marguerite Blessington




         Презентация начнется в
       течение нескольких минут ...


                                        Donets Basin
                                        Coal Mine-Ukraine
доброе утро
Fabio Akita, Co-Founder @CodeMiner42
“Off-centered software for
      off-centered people”
       Fabio Akita, Co-Founder @CodeMiner42
Understanding
the Rails Web Model
and Scalability Options
?
rails new app
somethings don’t change
CGI
1 request blocks 1 process
require 'rubygems'
require 'rack'

class Test
  def call(env)

    sleep 1 # on purpose, simulating a blocking operation

    [200, {"Content-Type" => "text/plain"},
      ["Hello World!"]]
  end
end

Rack::Handler::Thin.run Test.new
require 'rubygems'
require 'rack'

class Test
  def call(env)

    sleep 1 # on purpose, simulating a blocking operation

    [200, {"Content-Type" => "text/plain"},
      ["Hello World!"]]
  end
end

Rack::Handler::Thin.run Test.new
$ rackup config.ru

>> Thin web server (v1.3.1 codename Triple Espresso)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:8080, CTRL+C to stop
ab -n 10 -c 1 http://127.0.0.1:8080/

This is ApacheBench, Version 2.3 <$Revision: 1178079 $>
...
Concurrency Level:      1
Time taken for tests:   10.020 seconds
...
Requests per second:    1.00 [#/sec] (mean)
Time per request:       1002.015 [ms] (mean)
Time per request:       1002.015 [ms] (mean, across all concurrent requests)
Transfer rate:          0.12 [Kbytes/sec] received
...
ab -n 10 -c 1 http://127.0.0.1:8080/

This is ApacheBench, Version 2.3 <$Revision: 1178079 $>
...
Concurrency Level:      1
Time taken for tests:   10.020 seconds
...
Requests per second:    1.00 [#/sec] (mean)
Time per request:       1002.015 [ms] (mean)
Time per request:       1002.015 [ms] (mean, across all concurrent requests)
Transfer rate:          0.12 [Kbytes/sec] received
...
ab -n 10 -c 1 http://127.0.0.1:8080/

This is ApacheBench, Version 2.3 <$Revision: 1178079 $>
...
Concurrency Level:      1
Time taken for tests:   10.020 seconds
...
Requests per second:    1.00 [#/sec] (mean)
Time per request:       1002.015 [ms] (mean)
Time per request:       1002.015 [ms] (mean, across all concurrent requests)
Transfer rate:          0.12 [Kbytes/sec] received
...
ab -n 10 -c 1 http://127.0.0.1:8080/

This is ApacheBench, Version 2.3 <$Revision: 1178079 $>
...
Concurrency Level:      1
Time taken for tests:   10.020 seconds
...
Requests per second:    1.00 [#/sec] (mean)
Time per request:       1002.015 [ms] (mean)
Time per request:       1002.015 [ms] (mean, across all concurrent requests)
Transfer rate:          0.12 [Kbytes/sec] received
...
ab -n 10 -c 1 http://127.0.0.1:8080/

This is ApacheBench, Version 2.3 <$Revision: 1178079 $>
...
Concurrency Level:      1
Time taken for tests:   10.020 seconds
...
Requests per second:    1.00 [#/sec] (mean)
Time per request:       1002.015 [ms] (mean)
Time per request:       1002.015 [ms] (mean, across all concurrent requests)
Transfer rate:          0.12 [Kbytes/sec] received
...
Browser   Browser   Browser   Browser    Browser   Browser




                     NginX, HAProxy


                    Passenger, Unicorn
Optimize
Browser    Browser   Browser    Browser   Browser      Browser




                       NginX, HAProxy


          Passenger, Unicorn (CoW GC - REE or MRI 2)
Ruby Enterprise Edition 1.8.7    Copy on Write patched
 (about to be deprecated)         mark and sweep GC



    Ruby 1.9.2 (current)          mark and sweep GC



 Ruby 1.9.3 (transitioning)         Lazy Sweep GC



                                Copy on Write compatible
     Ruby 2.0 (future)
                                   Bitmap Marking GC
Ruby Enterprise Edition 1.8.7    Copy on Write patched
 (about to be deprecated)         mark and sweep GC



    Ruby 1.9.2 (current)          mark and sweep GC



 Ruby 1.9.3 (transitioning)         Lazy Sweep GC



                                Copy on Write compatible
     Ruby 2.0 (future)
                                   Bitmap Marking GC
Ruby Enterprise Edition 1.8.7    Copy on Write patched
 (about to be deprecated)         mark and sweep GC



    Ruby 1.9.2 (current)          mark and sweep GC



 Ruby 1.9.3 (transitioning)         Lazy Sweep GC



                                Copy on Write compatible
     Ruby 2.0 (future)
                                   Bitmap Marking GC
Ruby Enterprise Edition 1.8.7    Copy on Write patched
 (about to be deprecated)         mark and sweep GC



    Ruby 1.9.2 (current)          mark and sweep GC



 Ruby 1.9.3 (transitioning)         Lazy Sweep GC



                                Copy on Write compatible
     Ruby 2.0 (future)
                                   Bitmap Marking GC
Browser   Browser   Browser    Browser




           NginX, HAProxy

          Passenger, Unicorn
Browser   Browser   Browser    Browser




           NginX, HAProxy

          Passenger, Unicorn




             Memcached
Browser   Browser   Browser    Browser



               Varnish

           NginX, HAProxy

          Passenger, Unicorn




             Memcached
Browser   Browser   Browser    Browser



               Varnish

           NginX, HAProxy

          Passenger, Unicorn


                                         Resque


             Memcached
Browser   Browser   Browser    Browser



               Varnish

           NginX, HAProxy

          Passenger, Unicorn


                                         Resque


             Memcached
Too Long or
Periodic Polling
Notifications and Events in general


         Online Gaming


     Chatting and Presence


    Collaborative Applications


Advanced and more Interactive UI
(function poll(){

        $.ajax({ url: "server", success: function(data){
          // do something with the received ‘data’

          //Setup the next poll recursively
          poll();
        }, dataType: "json"});

})();
(function poll(){
   setTimeout(function(){
      $.ajax({ url: "server", success: function(data){
        // do something with the received ‘data’

        //Setup the next poll recursively
        poll();
      }, dataType: "json"});
  }, 5000);
})();
Cross Frame communication


          HTTP Polling (Ajax)


Liveconnect (Java applets, Flash socket)


             Long Polling


       Comet & HTTP Streaming
 (ex. forever frame/chunked encode)
W3C/IETF Standard - RFC 6455
                (12/2011)


Full duplex persistent communication channel


         Less overhead than HTTP
        (down to 2 bytes per frame)

       No latency (no reconnections)
      No polling overhead (on demand)

        “Upgrades” HTTP, uses 80/443
     (kind of friendly to existing proxies)
<script type="text/javascript">
  var ws = new WebSocket("ws://example.com:10081/");




</script>
<script type="text/javascript">
  var ws = new WebSocket("ws://example.com:10081/");

  ws.onopen = function() {
     ws.send("Hello"); // Sends a message.
  };

  ws.onmessage = function(e) {
     // Receives a message.
     alert(e.data);
  };

  ws.onclose = function() {
     alert("closed");
  };
</script>
Protocol        IE       Firefox      Chrome   Safari    Opera

hixie-75                                4        5

 hixie-76                    4          6       5.0.1       11
 hybi-00                 (disabled)                     (disabled)

hybi-06     HTML5 Labs     dev

hybi-07                      6

hybi-09     HTML5 Labs

hybi-10        IE 10         7          14

RFC 6455                     11         16
POLYFILL/FALLBACK
     (web-socket-js)
<script type="text/javascript" src="swfobject.js"></script>
<script type="text/javascript" src="web_socket.js"></script>
<script type="text/javascript">
  // Let the library know where WebSocketMain.swf is:
  WEB_SOCKET_SWF_LOCATION = "WebSocketMain.swf";

  var ws = new WebSocket("ws://example.com:10081/");
  ws.onopen = function() {
     ws.send("Hello"); // Sends a message.
  };
  ws.onmessage = function(e) {
     // Receives a message.
     alert(e.data);
  };
  ws.onclose = function() {
     alert("closed");
  };
</script>
<script type="text/javascript" src="swfobject.js"></script>
<script type="text/javascript" src="web_socket.js"></script>
<script type="text/javascript">
  // Let the library know where WebSocketMain.swf is:
  WEB_SOCKET_SWF_LOCATION = "WebSocketMain.swf";

  var ws = new WebSocket("ws://example.com:10081/");
  ws.onopen = function() {
     ws.send("Hello"); // Sends a message.
  };
  ws.onmessage = function(e) {
     // Receives a message.
     alert(e.data);
  };
  ws.onclose = function() {
     alert("closed");
  };
</script>
<script type="text/javascript" src="swfobject.js"></script>
<script type="text/javascript" src="web_socket.js"></script>
<script type="text/javascript">
  // Let the library know where WebSocketMain.swf is:
  WEB_SOCKET_SWF_LOCATION = "WebSocketMain.swf";

  var ws = new WebSocket("ws://example.com:10081/");
  ws.onopen = function() {
     ws.send("Hello"); // Sends a message.
  };
  ws.onmessage = function(e) {
     // Receives a message.
     alert(e.data);
  };
  ws.onclose = function() {
     alert("closed");
  };
</script>
<script type="text/javascript" src="swfobject.js"></script>
<script type="text/javascript" src="web_socket.js"></script>
<script type="text/javascript">
  // Let the library know where WebSocketMain.swf is:
  WEB_SOCKET_SWF_LOCATION = "WebSocketMain.swf";

  var ws = new WebSocket("ws://example.com:10081/");
  ws.onopen = function() {
     ws.send("Hello"); // Sends a message.
  };
  ws.onmessage = function(e) {
     // Receives a message.
     alert(e.data);
  };
  ws.onclose = function() {
     alert("closed");
  };
</script>
<script type="text/javascript" src="swfobject.js"></script>
<script type="text/javascript" src="web_socket.js"></script>
<script type="text/javascript">
  // Let the library know where WebSocketMain.swf is:
  WEB_SOCKET_SWF_LOCATION = "WebSocketMain.swf";

  var ws = new WebSocket("ws://example.com:10081/");
  ws.onopen = function() {
     ws.send("Hello"); // Sends a message.
  };
  ws.onmessage = function(e) {
     // Receives a message.
     alert(e.data);
  };
  ws.onclose = function() {
     alert("closed");
  };
</script>
Client: kind of OK
Server: what do do?
Long running requests
Reactor Pattern
   (Eventmachine)
synchronous I/O



non-blocking synchronous I/O



non-blocking asynchronous I/0
Wait Events
                (I/O, timers)




  Main Loop          Notifies Event
(main thread)          Handlers
select   poll
select   poll   epoll   kqueue   IOCP
libevent          libev


select       poll   epoll   kqueue   IOCP
Tornado


  Twisted


  libevent          libev


select       poll   epoll   kqueue   IOCP
Tornado


  Twisted           Node.js


  libevent           libev


select       poll    epoll    kqueue   IOCP
Tornado           Cool.io


  Twisted           Node.js


  libevent           libev


select       poll    epoll    kqueue   IOCP
Tornado           Cool.io


  Twisted           Node.js


  libevent           libev        EventMachine


select       poll    epoll    kqueue     IOCP
Tornado           Cool.io            Goliath


  Twisted           Node.js             Thin


  libevent           libev        EventMachine


select       poll    epoll    kqueue       IOCP
require 'rubygems'
require 'rack'

class Test
  def call(env)

    sleep 1 # on purpose, simulating a blocking operation

    [200, {"Content-Type" => "text/plain"},
      ["Hello World!"]]
  end
end

Rack::Handler::Thin.run Test.new
require 'rubygems'
require 'rack'

class Test
  def call(env)
    EM.defer do
      sleep 1 # CPU bound, throw to thread-pool (cheating)
    end
    [200, {"Content-Type" => "text/plain"},
      ["Hello World!"]]
  end
end

Rack::Handler::Thin.run Test.new
require 'rubygems'
require 'rack'

class Test
  def call(env)
    EM.defer do
      sleep 1 # CPU bound, throw to thread-pool (cheating)
    end
    [200, {"Content-Type" => "text/plain"},
      ["Hello World!"]]
  end
end

Rack::Handler::Thin.run Test.new
require 'rubygems'
require 'rack'

class Test
  def call(env)
    EM.defer do
      sleep 1 # CPU bound, throw to thread-pool (cheating)
    end
    [200, {"Content-Type" => "text/plain"},
      ["Hello World!"]]
  end
end

Rack::Handler::Thin.run Test.new
ab -n 10 -c 1 http://127.0.0.1:8080/
This is ApacheBench, Version 2.3 <$Revision: 1178079 $>
...
Concurrency Level:      1
Time taken for tests:   0.003 seconds
...
Requests per second:    3219.58 [#/sec] (mean)
Time per request:       0.311 [ms] (mean)
Time per request:       0.311 [ms] (mean, across all concurrent requests)
Transfer rate:          380.44 [Kbytes/sec] received
...
ab -n 10 -c 1 http://127.0.0.1:8080/
This is ApacheBench, Version 2.3 <$Revision: 1178079 $>
...
Concurrency Level:      1
Time taken for tests:   0.003 seconds
...
Requests per second:    3219.58 [#/sec] (mean)
Time per request:       0.311 [ms] (mean)
Time per request:       0.311 [ms] (mean, across all concurrent requests)
Transfer rate:          380.44 [Kbytes/sec] received
...
ab -n 10 -c 1 http://127.0.0.1:8080/
This is ApacheBench, Version 2.3 <$Revision: 1178079 $>
...
Concurrency Level:      1
Time taken for tests:   0.003 seconds
...
Requests per second:    3219.58 [#/sec] (mean)
Time per request:       0.311 [ms] (mean)
Time per request:       0.311 [ms] (mean, across all concurrent requests)
Transfer rate:          380.44 [Kbytes/sec] received
...
ab -n 10 -c 1 http://127.0.0.1:8080/
This is ApacheBench, Version 2.3 <$Revision: 1178079 $>
...
Concurrency Level:      1
Time taken for tests:   0.003 seconds
...
Requests per second:    3219.58 [#/sec] (mean)
Time per request:       0.311 [ms] (mean)
Time per request:       0.311 [ms] (mean, across all concurrent requests)
Transfer rate:          380.44 [Kbytes/sec] received
...
ab -n 10 -c 1 http://127.0.0.1:8080/
This is ApacheBench, Version 2.3 <$Revision: 1178079 $>
...
Concurrency Level:      1
Time taken for tests:   0.003 seconds
...
Requests per second:    3219.58 [#/sec] (mean)
Time per request:       0.311 [ms] (mean)
Time per request:       0.311 [ms] (mean, across all concurrent requests)
Transfer rate:          380.44 [Kbytes/sec] received
...
ab -n 10 -c 1 http://127.0.0.1:8080/
This is ApacheBench, Version 2.3 <$Revision: 1178079 $>

                                                          #ZOMG!
...
Concurrency Level:      1
Time taken for tests:   0.003 seconds
...
Requests per second:    3219.58 [#/sec] (mean)
Time per request:       0.311 [ms] (mean)
Time per request:       0.311 [ms] (mean, across all concurrent requests)
Transfer rate:          380.44 [Kbytes/sec] received
...
ab -n 10 -c 10 http://127.0.0.1:8080/
This is ApacheBench, Version 2.3 <$Revision: 1178079 $>
...
Concurrency Level:      10
Time taken for tests:   0.002 seconds
...
Requests per second:    5211.05 [#/sec] (mean)
Time per request:       1.919 [ms] (mean)
Time per request:       0.192 [ms] (mean, across all concurrent requests)
Transfer rate:          615.76 [Kbytes/sec] received
...
Block     Non-Block



 Total Time    10 sec   0.0001 sec

Requests per
  Second         1       + 8000
Block     Non-Block



 Total Time    10 sec   0.0001 sec

Requests per
  Second         1       + 8000
Block     Non-Block



 Total Time    10 sec   0.0001 sec

Requests per
  Second         1       + 8000
“Tick”
                      Timers
                    #add_timer
                 #add_periodic_timer




 Reactor Loop            Blocking Tasks
(Eventmachine)               #defer
                           #next_tick
require 'rubygems' # or use Bundler.setup
require 'eventmachine'

class EchoServer < EM::Connection
  def receive_data(data)
    if data.strip =~ /[exit|quit]$/i
      EM.stop
    else
      send_data("Repeating: #{data}")
    end
  end
end
require 'rubygems' # or use Bundler.setup
require 'eventmachine'

class EchoServer < EM::Connection
  def receive_data(data)
    if data.strip =~ /[exit|quit]$/i
      EM.stop
    else
      send_data("Repeating: #{data}")
    end
  end
end

EventMachine.run do
  # hit Control + C to stop
  Signal.trap("INT") { EM.stop }
  Signal.trap("TERM") { EM.stop }

  EM.start_server("0.0.0.0", 10000, EchoServer)
end
$ telnet localhost 10000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello World
$ telnet localhost 10000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello World
Repeating: Hello World
$ telnet localhost 10000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello World
Repeating: Hello World
Play again, Sam
$ telnet localhost 10000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello World
Repeating: Hello World
Play again, Sam
Repeating: Play again, Sam
$ telnet localhost 10000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello World
Repeating: Hello World
Play again, Sam
Repeating: Play again, Sam
quit
.
$ telnet localhost 10000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello World
Repeating: Hello World
Play again, Sam
Repeating: Play again, Sam
quit
Connection closed by foreign host.
require 'rubygems'
require 'eventmachine'

EM.run do
  # ... main reactor loop
  EM.stop # stop the main loop and exit
end
require 'rubygems'
require 'eventmachine'

EM.run   do
  puts   1
  puts   2
  puts   3
end
$ ruby em.rb
1
2
3
require 'rubygems'
require 'eventmachine'

EM.run do
  EM.defer do
    sleep 3
    puts 1
  end

  EM.add_timer(1) do
    puts 2

    EM.add_timer(1) do
      puts 3
    end
  end

  puts 4
end
$ ruby em.rb
4
2
3
1
var http = require('http');

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World');
}).listen(9876);
ab -n 1000 -c 5 http://127.0.0.1:9876/
This is ApacheBench, Version 2.3 <$Revision: 1178079 $>
...
Concurrency Level:      5
Time taken for tests:   0.124 seconds
...
Requests per second:    8035.36 [#/sec] (mean)
Time per request:       0.622 [ms] (mean)
Time per request:       0.124 [ms] (mean, across all concurrent requests)
Transfer rate:          588.53 [Kbytes/sec] received
...
require 'rubygems'
require 'rack'

Rack::Handler::Thin.run Proc.new {
  [200, {"Content-Type" => "text/plain"}, ["Hello World!"]]
}
ab -n 1000 -c 5 http://127.0.0.1:8080/
This is ApacheBench, Version 2.3 <$Revision: 1178079 $>
...
Concurrency Level:      5
Time taken for tests:   0.121 seconds
..
Requests per second:    8239.06 [#/sec] (mean)
Time per request:       0.607 [ms] (mean)
Time per request:       0.121 [ms] (mean, across all concurrent requests)
Transfer rate:          973.56 [Kbytes/sec] received
...
Node.js                     Ruby


        libev             Eventmachine, Cool.io


      Google V8            MRI, JRuby, Rubinius


Less Resources, Faster   More Resources, Slightly
      Processing           slower processing


    callbacks only       Threads, Fibers, Callbacks
Node.js                     Ruby


        libev             Eventmachine, Cool.io


      Google V8            MRI, JRuby, Rubinius


Less Resources, Faster   More Resources, Slightly
      Processing           slower processing


    callbacks only       Threads, Fibers, Callbacks
Node.js                     Ruby


        libev             Eventmachine, Cool.io


      Google V8            MRI, JRuby, Rubinius


Less Resources, Faster   More Resources, Slightly
      Processing           slower processing


    callbacks only       Threads, Fibers, Callbacks
Node.js                     Ruby


        libev             Eventmachine, Cool.io


      Google V8            MRI, JRuby, Rubinius


Less Resources, Faster   More Resources, Slightly
      Processing           slower processing


    callbacks only       Threads, Fibers, Callbacks
Node.js                     Ruby


        libev             Eventmachine, Cool.io


      Google V8            MRI, JRuby, Rubinius


Less Resources, Faster   More Resources, Slightly
      Processing           slower processing


    callbacks only       Threads, Fibers, Callbacks
EM-Websocket
require "rubygems"
require 'eventmachine'
require 'em-websocket'

config = {:host => "0.0.0.0", :port => 8080, :debug => true}
EM::WebSocket.start(config) do |ws|
  ws.onopen    { ws.send "Welcome!"}
  ws.onmessage { |msg| ws.send "Sending Pong: #{msg}" }
  ws.onclose   { puts "connection closed" }
  ws.onerror   { |e| puts "Error: #{e.message}" }
end
Caveats in Callback Driven
     Development
fs.rename('/tmp/hello', '/tmp/world', function (err) {
  if (err) throw err;
  console.log('renamed complete');
});

fs.stat('/tmp/world', function (err, stats) {
  if (err) throw err;
  console.log('stats: ' + JSON.stringify(stats));
});
fs.rename('/tmp/hello', '/tmp/world', function (err) {
  if (err) throw err;
  fs.stat('/tmp/world', function (err, stats) {
    if (err) throw err;
    console.log('stats: ' + JSON.stringify(stats));
  });
});
EM.run do
  page = EM::HttpRequest.new(@url1).get
  page.errback do
    puts "Site is down! terminate?"
  end
  page.callback do
    about = EM::HttpRequest.new(@url2).get
    about.callback do
      # callback nesting, ad infinitum
    end
    about.errback do
      # error-handling code
    end
  end
end
“Callback Spaghetti”
Ruby 1.9 Fibers
to the rescue!
number_generator = Fiber.new do
  start = 0
  loop do
    start += 1
    Fiber.yield(start)
  end
end
number_generator = Fiber.new do
  start = 0
  loop do
    start += 1
    Fiber.yield(start)
  end
end

> number_generator.resume
 => 1
number_generator = Fiber.new do
  start = 0
  loop do
    start += 1
    Fiber.yield(start)
  end
end

> number_generator.resume
 => 1
> number_generator.resume
 => 2
number_generator = Fiber.new do
  start = 0
  loop do
    start += 1
    Fiber.yield(start)
  end
end

> number_generator.resume
 => 1
> number_generator.resume
 => 2
> number_generator.resume
 => 3
Less expensive than Threads


      cooperative vs preemptive multitasking


          developer controls scheduling


     no need to have mutexes, no shared data


coroutines / can be implemented with continuations
Less expensive than Threads


      cooperative vs preemptive multitasking


          developer controls scheduling


     no need to have mutexes, no shared data


coroutines / can be implemented with continuations
Less expensive than Threads


      cooperative vs preemptive multitasking


          developer controls scheduling


     no need to have mutexes, no shared data


coroutines / can be implemented with continuations
Less expensive than Threads


      cooperative vs preemptive multitasking


          developer controls scheduling


     no need to have mutexes, no shared data


coroutines / can be implemented with continuations
Less expensive than Threads


      cooperative vs preemptive multitasking


          developer controls scheduling


     no need to have mutexes, no shared data


coroutines / can be implemented with continuations
EM.run do
  page = EM::HttpRequest.new(@url1).get
  page.errback do
    puts "Site is down! terminate?"
  end
  page.callback do
    about = EM::HttpRequest.new(@url2).get
    about.callback do
      # callback nesting, ad infinitum
    end
    about.errback do
      # error-handling code
    end
  end
end
page = http_get(@url1)
puts "Fetched page: #{page.response_header.status}"
if page
  page = http_get(@url2)
  puts "Fetched page 2: #{page.response_header.status}"
end
def http_get(url)
  f = Fiber.current
  http = EM::HttpRequest.new(url).get
  http.callback{ f.resume(http) }
  http.errback { f.resume(http) }
  return Fiber.yield
end

EM.run do
  Fiber.new do
    page = http_get(@url1)
    puts "Fetched page: #{page.response_header.status}"
    if page
      page = http_get(@url2)
      puts "Fetched page 2: #{page.response_header.status}"
    end
  do.resume
end
def http_get(url)
  f = Fiber.current
  http = EM::HttpRequest.new(url).get
  http.callback{ f.resume(http) }
  http.errback { f.resume(http) }
  return Fiber.yield
end

EM.run do
  Fiber.new do
    page = http_get(@url1)
    puts "Fetched page: #{page.response_header.status}"
    if page
      page = http_get(@url2)
      puts "Fetched page 2: #{page.response_header.status}"
    end
  do.resume
end
def http_get(url)
  f = Fiber.current
  http = EM::HttpRequest.new(url).get
  http.callback{ f.resume(http) }
  http.errback { f.resume(http) }
  return Fiber.yield
end

EM.run do
  Fiber.new do
    page = http_get(@url1)
    puts "Fetched page: #{page.response_header.status}"
    if page
      page = http_get(@url2)
      puts "Fetched page 2: #{page.response_header.status}"
    end
  do.resume
end
def http_get(url)
  f = Fiber.current
  http = EM::HttpRequest.new(url).get
  http.callback{ f.resume(http) }
  http.errback { f.resume(http) }
  return Fiber.yield
end

EM.run do
  Fiber.new do
    page = http_get(@url1)
    puts "Fetched page: #{page.response_header.status}"
    if page
      page = http_get(@url2)
      puts "Fetched page 2: #{page.response_header.status}"
    end
  do.resume
end
def http_get(url)
  f = Fiber.current
  http = EM::HttpRequest.new(url).get
  http.callback{ f.resume(http) }
  http.errback { f.resume(http) }
  return Fiber.yield
end

EM.run do
  Fiber.new do
    page = http_get(@url1)
    puts "Fetched page: #{page.response_header.status}"
    if page
      page = http_get(@url2)
      puts "Fetched page 2: #{page.response_header.status}"
    end
  do.resume
end
def http_get(url)
  f = Fiber.current
  http = EM::HttpRequest.new(url).get
  http.callback{ f.resume(http) }
  http.errback { f.resume(http) }
  return Fiber.yield
end

EM.run do
  Fiber.new do
    page = http_get(@url1)
    puts "Fetched page: #{page.response_header.status}"
    if page
      page = http_get(@url2)
      puts "Fetched page 2: #{page.response_header.status}"
    end
  do.resume
end
def http_get(url)
  f = Fiber.current
  http = EM::HttpRequest.new(url).get
  http.callback{ f.resume(http) }
  http.errback { f.resume(http) }
  return Fiber.yield
end

EM.run do
  Fiber.new do
    page = http_get(@url1)
    puts "Fetched page: #{page.response_header.status}"
    if page
      page = http_get(@url2)
      puts "Fetched page 2: #{page.response_header.status}"
    end
  do.resume
end
EM-Synchrony
EM.synchrony do
  page = EM::HttpRequest.new("http://www.google.com").get
  puts "Look Ma! No callbacks! Fetched page: #{page}"
  EM.stop
end

# old way
EM.run do
  page = EM::HttpRequest.new("http://www.google.com").get
  page.callback do
    puts "Lame ... Fetched page: #{page}"
    EM.stop
  end
end
Goliath
require 'goliath'
require 'yajl'

G = Goliath::Rack # don’t to this, just to fit in this slide :-)
class Echo < Goliath::API
  use G::Render, 'json' # auto-negotiate response format
  use G::Params         # parse & merge query and body parameters
  use G::Validation::RequiredParam, {:key => 'echo'}

  def process_request
    logger.info "Processing request"
    {response: env.params['echo']}
  end

  def response(env)
    [200, {}, process_request]
  end
end
$ ruby echo.rb -p 9001
$ ruby echo.rb -p 9001

$ curl http://localhost:9001/
{"error":"Echo identifier missing"}
$ ruby echo.rb -p 9001

$ curl http://localhost:9001/
{"error":"Echo identifier missing"}

$ curl http://localhost:9001?echo=Hello%20World
{"response":"Hello World"}
Web App Server and App Framework


         Fully asynchronous using Eventmachine


Lightweight and High Performance (+ 3k req/s in 1 process)


       Rack aware (but not 100% Rack compatible)


    Fibers with EM-Synchrony for easier development
Recap so far ...
Ruby can using Reactors to massively scale


        Good contender to Node.js-style
               (getting better)

One single Ruby process can handle thousands of
              concurrent requests


  Web browsers got smarter with Websockets


     Ruby implements Websocket support
Pusher
Browser           Persistent
                                 connection!


                 async

  Rails App                       Eventmachine App




Resque Queues             sync
Browser           Persistent
                                 connection!


                 async

  Rails App                       Eventmachine App




Resque Queues             sync
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/
jquery.min.js"></script>
<script src="http://js.pusher.com/1.11/pusher.min.js"></script>
<script>
  var pusher = new Pusher('7114e...c318e');
  var channel = pusher.subscribe('demo-channel');




</script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/
jquery.min.js"></script>
<script src="http://js.pusher.com/1.11/pusher.min.js"></script>
<script>
  var pusher = new Pusher('7114e...c318e');
  var channel = pusher.subscribe('demo-channel');

  channel.bind('create', function(message) {
    var elem = $("#" + message.elem_id);
    if (elem) elem.remove();
    var html = "<li id='" + message.elem_id + "'>" +
      message.elem_id + " - " + message.value + "</li>";
    $("#list").append(html);
  });

  channel.bind('delete', function(message) {
    var elem = $("#" + message.elem_id);
    if (elem) elem.remove();
  });
</script>
require 'rubygems'
require 'pusher'

Pusher.app_id = '14909'
Pusher.key = '7114e...c318e'
Pusher.secret = '25aa7...3d49c'

('a'..'z').each do |letter|
  doc = { :elem_id => letter,
          :value   => "Letter: #{letter}"}
  Pusher['demo-channel'].trigger('create', doc)
end
time ruby pusher_sync.rb

real 0m14.585s
user 0m0.583s
sys 0m0.105s
require 'rubygems'
require 'pusher'
require 'eventmachine'

Pusher.app_id = '14909'
Pusher.key = '7114e...c318e'
Pusher.secret = '25aa7...d49c'

EM.run do
  EM::Iterator.new("a".."z").each do |letter, iter|
    doc = { :elem_id => elem_id,
            :value   => "Letter: #{letter}" }
    pusher = Pusher['demo-channel'].trigger_async('create', doc)
    pusher.callback { EM.stop if letter == 'z' }
    pusher.errback { |error| EM.stop if letter == 'z' }
    iter.next
  end
end
require 'rubygems'
require 'pusher'
require 'eventmachine'

Pusher.app_id = '14909'
Pusher.key = '7114e...c318e'
Pusher.secret = '25aa7...d49c'

EM.run do
  EM::Iterator.new("a".."z").each do |letter, iter|
    doc = { :elem_id => elem_id,
            :value   => "Letter: #{letter}" }
    pusher = Pusher['demo-channel'].trigger_async('create', doc)
    pusher.callback { EM.stop if letter == 'z' }
    pusher.errback { |error| EM.stop if letter == 'z' }
    iter.next
  end
end
require 'rubygems'
require 'pusher'
require 'eventmachine'

Pusher.app_id = '14909'
Pusher.key = '7114e...c318e'
Pusher.secret = '25aa7...d49c'

EM.run do
  EM::Iterator.new("a".."z").each do |letter, iter|
    doc = { :elem_id => elem_id,
            :value   => "Letter: #{letter}" }
    pusher = Pusher['demo-channel'].trigger_async('create', doc)
    pusher.callback { EM.stop if letter == 'z' }
    pusher.errback { |error| EM.stop if letter == 'z' }
    iter.next
  end
end
time ruby pusher_async.rb

real 0m1.129s
user 0m0.649s
sys 0m0.063s
pusher.connection.bind('connected', function() {
  alert("You're up!")
});

pusher.connection.bind('connecting_in', function(delay) {
  alert("Retrying in " + delay + " seconds.")
});

pusher.connection.bind('failed', function() {
  document.write("Not able to connect.")
});
Private Channels



  Encryption



 Authentication



Presence Events
Total API requests (11/02/2011)

  (day has 86.400 seconds)
13.969.264
 Total API requests (11/02/2011)

   (day has 86.400 seconds)
Amount of messages sent
to clients since launch (11/02/2011)
35.552.810.379
        Amount of messages sent
   to clients since launch (11/02/2011)
average latency (excluding internet - 11/02/2011)
< 10ms
average latency (excluding internet - 11/02/2011)
Wrapping up ...
CGI model is difficult to scale


Multi-processes vs multi-threads vs Reactors


         HTTP 5 WebSockets is hot!


           Eventmachine is great!


       Fibers vs “callback spaghetti”


              Try out Pusher!
CGI model is difficult to scale


Multi-processes vs multi-threads vs Reactors


         HTTP 5 WebSockets is hot!


           Eventmachine is great!


       Fibers vs “callback spaghetti”


              Try out Pusher!
CGI model is difficult to scale


Multi-processes vs multi-threads vs Reactors


         HTTP 5 WebSockets is hot!


           Eventmachine is great!


       Fibers vs “callback spaghetti”


              Try out Pusher!
CGI model is difficult to scale


Multi-processes vs multi-threads vs Reactors


         HTTP 5 WebSockets is hot!


           Eventmachine is great!


       Fibers vs “callback spaghetti”


              Try out Pusher!
CGI model is difficult to scale


Multi-processes vs multi-threads vs Reactors


         HTTP 5 WebSockets is hot!


           Eventmachine is great!


       Fibers vs “callback spaghetti”


              Try out Pusher!
CGI model is difficult to scale


Multi-processes vs multi-threads vs Reactors


         HTTP 5 WebSockets is hot!


           Eventmachine is great!


       Fibers vs “callback spaghetti”


              Try out Pusher!
Ilya Grigorik
   (igvita)
PostRank (acquired by Google!)




    EM-Synchrony, Goliath




    Google SPDY research
Tony Arcieri
 (bascule)
Rev (later Cool.io), Revactor




                   Reia
(Ruby syntax over Erlang, replaced by Elixir)



 Celluloid (Threads abstraction to Actors)
  (Mark Perham used to create Sidekiq)
Ruby is very flexible
one more thing ...
Browser   Browser   Browser   Browser    Browser   Browser




                     NginX, HAProxy


                    Passenger, Unicorn
Browser   Browser   Browser   Browser    Browser   Browser




                     NginX, HAProxy




              JRuby - TorqueBox, Trinidad
           (multiple concurrent native threads)
Native threads
Ruby 1.9.x
             (extensions can release the GIL)



                     Native threads
 JRuby
                        (no GIL)


                     Native threads
Rubinius                 (no GIL
             check out the Puma webserver)
Native threads
Ruby 1.9.x
             (extensions can release the GIL)



                     Native threads
 JRuby
                        (no GIL)


                     Native threads
Rubinius                 (no GIL
             check out the Puma webserver)
Native threads
Ruby 1.9.x
             (extensions can release the GIL)



                     Native threads
 JRuby
                        (no GIL)


                     Native threads
Rubinius                 (no GIL
             check out the Puma webserver)
Большое
спасибо
  www.codeminer.com.br
  www.akitaonrails.com
  @akitaonrails

More Related Content

What's hot

0-60 with Goliath: Building High Performance Ruby Web-Services
0-60 with Goliath: Building High Performance Ruby Web-Services0-60 with Goliath: Building High Performance Ruby Web-Services
0-60 with Goliath: Building High Performance Ruby Web-ServicesIlya Grigorik
 
Faster & Greater Messaging System HornetQ zzz
Faster & Greater Messaging System HornetQ zzzFaster & Greater Messaging System HornetQ zzz
Faster & Greater Messaging System HornetQ zzzJBug Italy
 
JUDCon 2010 Boston : BoxGrinder
JUDCon 2010 Boston : BoxGrinderJUDCon 2010 Boston : BoxGrinder
JUDCon 2010 Boston : BoxGrindermarekgoldmann
 
Apache httpd reverse proxy and Tomcat
Apache httpd reverse proxy and TomcatApache httpd reverse proxy and Tomcat
Apache httpd reverse proxy and TomcatJean-Frederic Clere
 
Fisl - Deployment
Fisl - DeploymentFisl - Deployment
Fisl - DeploymentFabio Akita
 
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...Ontico
 
Apache httpd 2.4: The Cloud Killer App
Apache httpd 2.4: The Cloud Killer AppApache httpd 2.4: The Cloud Killer App
Apache httpd 2.4: The Cloud Killer AppJim Jagielski
 
Supercharging reflective libraries with InvokeDynamic
Supercharging reflective libraries with InvokeDynamicSupercharging reflective libraries with InvokeDynamic
Supercharging reflective libraries with InvokeDynamicIan Robertson
 
Writing Portable WebSockets in Java
Writing Portable WebSockets in JavaWriting Portable WebSockets in Java
Writing Portable WebSockets in Javajfarcand
 
TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011bobmcwhirter
 
Java/Spring과 Node.js의공존
Java/Spring과 Node.js의공존Java/Spring과 Node.js의공존
Java/Spring과 Node.js의공존동수 장
 
JUDCon 2010 Boston : TorqueBox
JUDCon 2010 Boston : TorqueBoxJUDCon 2010 Boston : TorqueBox
JUDCon 2010 Boston : TorqueBoxmarekgoldmann
 
When Ruby Meets Java - The Power of Torquebox
When Ruby Meets Java - The Power of TorqueboxWhen Ruby Meets Java - The Power of Torquebox
When Ruby Meets Java - The Power of Torqueboxrockyjaiswal
 
"Swoole: double troubles in c", Alexandr Vronskiy
"Swoole: double troubles in c", Alexandr Vronskiy"Swoole: double troubles in c", Alexandr Vronskiy
"Swoole: double troubles in c", Alexandr VronskiyFwdays
 
How to test code with mruby
How to test code with mrubyHow to test code with mruby
How to test code with mrubyHiroshi SHIBATA
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applicationsTom Croucher
 
The Future of library dependency management of Ruby
 The Future of library dependency management of Ruby The Future of library dependency management of Ruby
The Future of library dependency management of RubyHiroshi SHIBATA
 
Java/Spring과 Node.js의 공존 시즌2
Java/Spring과 Node.js의 공존 시즌2Java/Spring과 Node.js의 공존 시즌2
Java/Spring과 Node.js의 공존 시즌2동수 장
 
OWASP ZAP Workshop for QA Testers
OWASP ZAP Workshop for QA TestersOWASP ZAP Workshop for QA Testers
OWASP ZAP Workshop for QA TestersJavan Rasokat
 

What's hot (20)

0-60 with Goliath: Building High Performance Ruby Web-Services
0-60 with Goliath: Building High Performance Ruby Web-Services0-60 with Goliath: Building High Performance Ruby Web-Services
0-60 with Goliath: Building High Performance Ruby Web-Services
 
Plack at OSCON 2010
Plack at OSCON 2010Plack at OSCON 2010
Plack at OSCON 2010
 
Faster & Greater Messaging System HornetQ zzz
Faster & Greater Messaging System HornetQ zzzFaster & Greater Messaging System HornetQ zzz
Faster & Greater Messaging System HornetQ zzz
 
JUDCon 2010 Boston : BoxGrinder
JUDCon 2010 Boston : BoxGrinderJUDCon 2010 Boston : BoxGrinder
JUDCon 2010 Boston : BoxGrinder
 
Apache httpd reverse proxy and Tomcat
Apache httpd reverse proxy and TomcatApache httpd reverse proxy and Tomcat
Apache httpd reverse proxy and Tomcat
 
Fisl - Deployment
Fisl - DeploymentFisl - Deployment
Fisl - Deployment
 
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...
 
Apache httpd 2.4: The Cloud Killer App
Apache httpd 2.4: The Cloud Killer AppApache httpd 2.4: The Cloud Killer App
Apache httpd 2.4: The Cloud Killer App
 
Supercharging reflective libraries with InvokeDynamic
Supercharging reflective libraries with InvokeDynamicSupercharging reflective libraries with InvokeDynamic
Supercharging reflective libraries with InvokeDynamic
 
Writing Portable WebSockets in Java
Writing Portable WebSockets in JavaWriting Portable WebSockets in Java
Writing Portable WebSockets in Java
 
TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011
 
Java/Spring과 Node.js의공존
Java/Spring과 Node.js의공존Java/Spring과 Node.js의공존
Java/Spring과 Node.js의공존
 
JUDCon 2010 Boston : TorqueBox
JUDCon 2010 Boston : TorqueBoxJUDCon 2010 Boston : TorqueBox
JUDCon 2010 Boston : TorqueBox
 
When Ruby Meets Java - The Power of Torquebox
When Ruby Meets Java - The Power of TorqueboxWhen Ruby Meets Java - The Power of Torquebox
When Ruby Meets Java - The Power of Torquebox
 
"Swoole: double troubles in c", Alexandr Vronskiy
"Swoole: double troubles in c", Alexandr Vronskiy"Swoole: double troubles in c", Alexandr Vronskiy
"Swoole: double troubles in c", Alexandr Vronskiy
 
How to test code with mruby
How to test code with mrubyHow to test code with mruby
How to test code with mruby
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
The Future of library dependency management of Ruby
 The Future of library dependency management of Ruby The Future of library dependency management of Ruby
The Future of library dependency management of Ruby
 
Java/Spring과 Node.js의 공존 시즌2
Java/Spring과 Node.js의 공존 시즌2Java/Spring과 Node.js의 공존 시즌2
Java/Spring과 Node.js의 공존 시즌2
 
OWASP ZAP Workshop for QA Testers
OWASP ZAP Workshop for QA TestersOWASP ZAP Workshop for QA Testers
OWASP ZAP Workshop for QA Testers
 

Viewers also liked

Aorist Middle Participles
Aorist Middle ParticiplesAorist Middle Participles
Aorist Middle ParticiplesKevin Smith
 
Use credit union home loan basics 2 28 12
Use credit union home loan basics 2 28 12Use credit union home loan basics 2 28 12
Use credit union home loan basics 2 28 12mullarkea
 
Social networkingforwriters
Social networkingforwritersSocial networkingforwriters
Social networkingforwritersDana Goldstein
 
Translation #5 in the nearness and distance (chinese and malay)
Translation #5 in the nearness and distance (chinese and malay)Translation #5 in the nearness and distance (chinese and malay)
Translation #5 in the nearness and distance (chinese and malay)Isaac Low
 
CUbRIK Fashion Trend Analysis: a Business Intelligence Application
CUbRIK Fashion Trend Analysis: a Business Intelligence ApplicationCUbRIK Fashion Trend Analysis: a Business Intelligence Application
CUbRIK Fashion Trend Analysis: a Business Intelligence ApplicationCUbRIK Project
 
CUbRIK research at LS-COOP workshop
CUbRIK research at LS-COOP workshopCUbRIK research at LS-COOP workshop
CUbRIK research at LS-COOP workshopCUbRIK Project
 
Evolution of money.united miners club
Evolution of money.united miners clubEvolution of money.united miners club
Evolution of money.united miners clubSalvador Trasmonte
 
C++ en-iyi-egitimi
C++ en-iyi-egitimiC++ en-iyi-egitimi
C++ en-iyi-egitimisersld29
 
C egitimi-umraniye
C egitimi-umraniyeC egitimi-umraniye
C egitimi-umraniyesersld29
 

Viewers also liked (16)

02 The Wise Men
02 The Wise Men02 The Wise Men
02 The Wise Men
 
Aorist Middle Participles
Aorist Middle ParticiplesAorist Middle Participles
Aorist Middle Participles
 
Use credit union home loan basics 2 28 12
Use credit union home loan basics 2 28 12Use credit union home loan basics 2 28 12
Use credit union home loan basics 2 28 12
 
Social networkingforwriters
Social networkingforwritersSocial networkingforwriters
Social networkingforwriters
 
Translation #5 in the nearness and distance (chinese and malay)
Translation #5 in the nearness and distance (chinese and malay)Translation #5 in the nearness and distance (chinese and malay)
Translation #5 in the nearness and distance (chinese and malay)
 
My story ed511
My story ed511My story ed511
My story ed511
 
My story ED 511
My story ED 511My story ED 511
My story ED 511
 
CUbRIK Fashion Trend Analysis: a Business Intelligence Application
CUbRIK Fashion Trend Analysis: a Business Intelligence ApplicationCUbRIK Fashion Trend Analysis: a Business Intelligence Application
CUbRIK Fashion Trend Analysis: a Business Intelligence Application
 
CUbRIK research at LS-COOP workshop
CUbRIK research at LS-COOP workshopCUbRIK research at LS-COOP workshop
CUbRIK research at LS-COOP workshop
 
Evolution of money.united miners club
Evolution of money.united miners clubEvolution of money.united miners club
Evolution of money.united miners club
 
Plancha2 2012
Plancha2 2012Plancha2 2012
Plancha2 2012
 
C++ en-iyi-egitimi
C++ en-iyi-egitimiC++ en-iyi-egitimi
C++ en-iyi-egitimi
 
Teorija
TeorijaTeorija
Teorija
 
La classe come un set
La classe come un setLa classe come un set
La classe come un set
 
C egitimi-umraniye
C egitimi-umraniyeC egitimi-umraniye
C egitimi-umraniye
 
C 2019
C 2019C 2019
C 2019
 

Similar to Understanding the Rails web model and scalability options

Nodejs a-practical-introduction-oredev
Nodejs a-practical-introduction-oredevNodejs a-practical-introduction-oredev
Nodejs a-practical-introduction-oredevFelix Geisendörfer
 
Dynamic Languages Web Frameworks Indicthreads 2009
Dynamic Languages Web Frameworks Indicthreads 2009Dynamic Languages Web Frameworks Indicthreads 2009
Dynamic Languages Web Frameworks Indicthreads 2009Arun Gupta
 
VUG5: Varnish at Opera Software
VUG5: Varnish at Opera SoftwareVUG5: Varnish at Opera Software
VUG5: Varnish at Opera SoftwareCosimo Streppone
 
Nodejs Explained with Examples
Nodejs Explained with ExamplesNodejs Explained with Examples
Nodejs Explained with ExamplesGabriele Lana
 
Nodejsexplained 101116115055-phpapp02
Nodejsexplained 101116115055-phpapp02Nodejsexplained 101116115055-phpapp02
Nodejsexplained 101116115055-phpapp02Sunny Gupta
 
Isomorphic JavaScript with Nashorn
Isomorphic JavaScript with NashornIsomorphic JavaScript with Nashorn
Isomorphic JavaScript with NashornMaxime Najim
 
Socket applications
Socket applicationsSocket applications
Socket applicationsJoão Moura
 
Cape Cod Web Technology Meetup - 2
Cape Cod Web Technology Meetup - 2Cape Cod Web Technology Meetup - 2
Cape Cod Web Technology Meetup - 2Asher Martin
 
Vert.x – The problem of real-time data binding
Vert.x – The problem of real-time data bindingVert.x – The problem of real-time data binding
Vert.x – The problem of real-time data bindingAlex Derkach
 
Writing highly scalable WebSocket using the Atmosphere Framework and Scala
Writing highly scalable WebSocket using the Atmosphere Framework and ScalaWriting highly scalable WebSocket using the Atmosphere Framework and Scala
Writing highly scalable WebSocket using the Atmosphere Framework and Scalajfarcand
 
Nodejs and WebSockets
Nodejs and WebSocketsNodejs and WebSockets
Nodejs and WebSocketsGonzalo Ayuso
 
Going Live! with Comet
Going Live! with CometGoing Live! with Comet
Going Live! with CometSimon Willison
 
.NET Architects Day - DNAD 2011
.NET Architects Day - DNAD 2011.NET Architects Day - DNAD 2011
.NET Architects Day - DNAD 2011Fabio Akita
 
09 - Fábio Akita - Além do rails
09 - Fábio Akita - Além do rails09 - Fábio Akita - Além do rails
09 - Fábio Akita - Além do railsDNAD
 
Eduardo Silva - monkey http-server everywhere
Eduardo Silva - monkey http-server everywhereEduardo Silva - monkey http-server everywhere
Eduardo Silva - monkey http-server everywhereStarTech Conference
 
WebSockets: The Current State of the Most Valuable HTML5 API for Java Developers
WebSockets: The Current State of the Most Valuable HTML5 API for Java DevelopersWebSockets: The Current State of the Most Valuable HTML5 API for Java Developers
WebSockets: The Current State of the Most Valuable HTML5 API for Java DevelopersViktor Gamov
 

Similar to Understanding the Rails web model and scalability options (20)

Deployment de Rails
Deployment de RailsDeployment de Rails
Deployment de Rails
 
The HTML5 WebSocket API
The HTML5 WebSocket APIThe HTML5 WebSocket API
The HTML5 WebSocket API
 
Nodejs a-practical-introduction-oredev
Nodejs a-practical-introduction-oredevNodejs a-practical-introduction-oredev
Nodejs a-practical-introduction-oredev
 
Dynamic Languages Web Frameworks Indicthreads 2009
Dynamic Languages Web Frameworks Indicthreads 2009Dynamic Languages Web Frameworks Indicthreads 2009
Dynamic Languages Web Frameworks Indicthreads 2009
 
VUG5: Varnish at Opera Software
VUG5: Varnish at Opera SoftwareVUG5: Varnish at Opera Software
VUG5: Varnish at Opera Software
 
Nodejs Explained with Examples
Nodejs Explained with ExamplesNodejs Explained with Examples
Nodejs Explained with Examples
 
Nodejsexplained 101116115055-phpapp02
Nodejsexplained 101116115055-phpapp02Nodejsexplained 101116115055-phpapp02
Nodejsexplained 101116115055-phpapp02
 
Isomorphic JavaScript with Nashorn
Isomorphic JavaScript with NashornIsomorphic JavaScript with Nashorn
Isomorphic JavaScript with Nashorn
 
Socket applications
Socket applicationsSocket applications
Socket applications
 
Cape Cod Web Technology Meetup - 2
Cape Cod Web Technology Meetup - 2Cape Cod Web Technology Meetup - 2
Cape Cod Web Technology Meetup - 2
 
Vert.x – The problem of real-time data binding
Vert.x – The problem of real-time data bindingVert.x – The problem of real-time data binding
Vert.x – The problem of real-time data binding
 
Writing highly scalable WebSocket using the Atmosphere Framework and Scala
Writing highly scalable WebSocket using the Atmosphere Framework and ScalaWriting highly scalable WebSocket using the Atmosphere Framework and Scala
Writing highly scalable WebSocket using the Atmosphere Framework and Scala
 
JS everywhere 2011
JS everywhere 2011JS everywhere 2011
JS everywhere 2011
 
Time for Comet?
Time for Comet?Time for Comet?
Time for Comet?
 
Nodejs and WebSockets
Nodejs and WebSocketsNodejs and WebSockets
Nodejs and WebSockets
 
Going Live! with Comet
Going Live! with CometGoing Live! with Comet
Going Live! with Comet
 
.NET Architects Day - DNAD 2011
.NET Architects Day - DNAD 2011.NET Architects Day - DNAD 2011
.NET Architects Day - DNAD 2011
 
09 - Fábio Akita - Além do rails
09 - Fábio Akita - Além do rails09 - Fábio Akita - Além do rails
09 - Fábio Akita - Além do rails
 
Eduardo Silva - monkey http-server everywhere
Eduardo Silva - monkey http-server everywhereEduardo Silva - monkey http-server everywhere
Eduardo Silva - monkey http-server everywhere
 
WebSockets: The Current State of the Most Valuable HTML5 API for Java Developers
WebSockets: The Current State of the Most Valuable HTML5 API for Java DevelopersWebSockets: The Current State of the Most Valuable HTML5 API for Java Developers
WebSockets: The Current State of the Most Valuable HTML5 API for Java Developers
 

More from .toster

Native look and feel bbui & alicejs
Native look and feel bbui & alicejsNative look and feel bbui & alicejs
Native look and feel bbui & alicejs.toster
 
Практики применения JRuby
Практики применения JRubyПрактики применения JRuby
Практики применения JRuby.toster
 
Sinatra: прошлое, будущее и настоящее
Sinatra: прошлое, будущее и настоящееSinatra: прошлое, будущее и настоящее
Sinatra: прошлое, будущее и настоящее.toster
 
Attributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active recordAttributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active record.toster
 
Decyphering Rails 3
Decyphering Rails 3Decyphering Rails 3
Decyphering Rails 3.toster
 
Михаил Черномордиков
Михаил ЧерномордиковМихаил Черномордиков
Михаил Черномордиков.toster
 
Андрей Юношев
Андрей Юношев Андрей Юношев
Андрей Юношев .toster
 
Алексей Тарасенко - Zeptolab
Алексей Тарасенко - ZeptolabАлексей Тарасенко - Zeptolab
Алексей Тарасенко - Zeptolab.toster
 
Maximiliano Firtman - Разработка приложений с помощью PhoneGap
Maximiliano Firtman - Разработка приложений с помощью PhoneGap Maximiliano Firtman - Разработка приложений с помощью PhoneGap
Maximiliano Firtman - Разработка приложений с помощью PhoneGap .toster
 
Вадим Башуров
Вадим БашуровВадим Башуров
Вадим Башуров.toster
 
Вадим Башуров - Как откусить от яблока лимон
Вадим Башуров - Как откусить от яблока лимонВадим Башуров - Как откусить от яблока лимон
Вадим Башуров - Как откусить от яблока лимон.toster
 
Вадим Башуров - Как откусить от яблока лимон
Вадим Башуров - Как откусить от яблока лимонВадим Башуров - Как откусить от яблока лимон
Вадим Башуров - Как откусить от яблока лимон.toster
 
Pablo Villalba -
Pablo Villalba - Pablo Villalba -
Pablo Villalba - .toster
 
Jordi Romero Api for-the-mobile-era
Jordi Romero Api for-the-mobile-eraJordi Romero Api for-the-mobile-era
Jordi Romero Api for-the-mobile-era.toster
 
Презентация Юрия Ветрова (Mail.ru Group)
Презентация Юрия Ветрова (Mail.ru Group)Презентация Юрия Ветрова (Mail.ru Group)
Презентация Юрия Ветрова (Mail.ru Group).toster
 
Внутренняя архитектура и устройства соц. сети "Одноклассники"
Внутренняя архитектура и устройства соц. сети "Одноклассники"Внутренняя архитектура и устройства соц. сети "Одноклассники"
Внутренняя архитектура и устройства соц. сети "Одноклассники".toster
 
Reusable Code, for good or for awesome!
Reusable Code, for good or for awesome!Reusable Code, for good or for awesome!
Reusable Code, for good or for awesome!.toster
 
Matthew Eernisse, NodeJs, .toster {webdev}
Matthew Eernisse, NodeJs, .toster {webdev}Matthew Eernisse, NodeJs, .toster {webdev}
Matthew Eernisse, NodeJs, .toster {webdev}.toster
 
Wild wild web. html5 era
Wild wild web. html5 eraWild wild web. html5 era
Wild wild web. html5 era.toster
 
Web matrix
Web matrixWeb matrix
Web matrix.toster
 

More from .toster (20)

Native look and feel bbui & alicejs
Native look and feel bbui & alicejsNative look and feel bbui & alicejs
Native look and feel bbui & alicejs
 
Практики применения JRuby
Практики применения JRubyПрактики применения JRuby
Практики применения JRuby
 
Sinatra: прошлое, будущее и настоящее
Sinatra: прошлое, будущее и настоящееSinatra: прошлое, будущее и настоящее
Sinatra: прошлое, будущее и настоящее
 
Attributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active recordAttributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active record
 
Decyphering Rails 3
Decyphering Rails 3Decyphering Rails 3
Decyphering Rails 3
 
Михаил Черномордиков
Михаил ЧерномордиковМихаил Черномордиков
Михаил Черномордиков
 
Андрей Юношев
Андрей Юношев Андрей Юношев
Андрей Юношев
 
Алексей Тарасенко - Zeptolab
Алексей Тарасенко - ZeptolabАлексей Тарасенко - Zeptolab
Алексей Тарасенко - Zeptolab
 
Maximiliano Firtman - Разработка приложений с помощью PhoneGap
Maximiliano Firtman - Разработка приложений с помощью PhoneGap Maximiliano Firtman - Разработка приложений с помощью PhoneGap
Maximiliano Firtman - Разработка приложений с помощью PhoneGap
 
Вадим Башуров
Вадим БашуровВадим Башуров
Вадим Башуров
 
Вадим Башуров - Как откусить от яблока лимон
Вадим Башуров - Как откусить от яблока лимонВадим Башуров - Как откусить от яблока лимон
Вадим Башуров - Как откусить от яблока лимон
 
Вадим Башуров - Как откусить от яблока лимон
Вадим Башуров - Как откусить от яблока лимонВадим Башуров - Как откусить от яблока лимон
Вадим Башуров - Как откусить от яблока лимон
 
Pablo Villalba -
Pablo Villalba - Pablo Villalba -
Pablo Villalba -
 
Jordi Romero Api for-the-mobile-era
Jordi Romero Api for-the-mobile-eraJordi Romero Api for-the-mobile-era
Jordi Romero Api for-the-mobile-era
 
Презентация Юрия Ветрова (Mail.ru Group)
Презентация Юрия Ветрова (Mail.ru Group)Презентация Юрия Ветрова (Mail.ru Group)
Презентация Юрия Ветрова (Mail.ru Group)
 
Внутренняя архитектура и устройства соц. сети "Одноклассники"
Внутренняя архитектура и устройства соц. сети "Одноклассники"Внутренняя архитектура и устройства соц. сети "Одноклассники"
Внутренняя архитектура и устройства соц. сети "Одноклассники"
 
Reusable Code, for good or for awesome!
Reusable Code, for good or for awesome!Reusable Code, for good or for awesome!
Reusable Code, for good or for awesome!
 
Matthew Eernisse, NodeJs, .toster {webdev}
Matthew Eernisse, NodeJs, .toster {webdev}Matthew Eernisse, NodeJs, .toster {webdev}
Matthew Eernisse, NodeJs, .toster {webdev}
 
Wild wild web. html5 era
Wild wild web. html5 eraWild wild web. html5 era
Wild wild web. html5 era
 
Web matrix
Web matrixWeb matrix
Web matrix
 

Recently uploaded

08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 

Recently uploaded (20)

08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 

Understanding the Rails web model and scalability options

  • 1. “ Genius is the gold in the mine; talent is the miner who works and brings it out. ” Lady Marguerite Blessington Donets Basin Coal Mine-Ukraine
  • 2. “ Genius is the gold in the mine; talent is the miner who works and brings it out. ” Lady Marguerite Blessington Презентация начнется в течение нескольких минут ... Donets Basin Coal Mine-Ukraine
  • 4. Fabio Akita, Co-Founder @CodeMiner42
  • 5. “Off-centered software for off-centered people” Fabio Akita, Co-Founder @CodeMiner42
  • 6.
  • 7.
  • 8. Understanding the Rails Web Model and Scalability Options
  • 9. ?
  • 10.
  • 11.
  • 13.
  • 15.
  • 16. CGI
  • 17. 1 request blocks 1 process
  • 18. require 'rubygems' require 'rack' class Test def call(env) sleep 1 # on purpose, simulating a blocking operation [200, {"Content-Type" => "text/plain"}, ["Hello World!"]] end end Rack::Handler::Thin.run Test.new
  • 19. require 'rubygems' require 'rack' class Test def call(env) sleep 1 # on purpose, simulating a blocking operation [200, {"Content-Type" => "text/plain"}, ["Hello World!"]] end end Rack::Handler::Thin.run Test.new
  • 20. $ rackup config.ru >> Thin web server (v1.3.1 codename Triple Espresso) >> Maximum connections set to 1024 >> Listening on 0.0.0.0:8080, CTRL+C to stop
  • 21. ab -n 10 -c 1 http://127.0.0.1:8080/ This is ApacheBench, Version 2.3 <$Revision: 1178079 $> ... Concurrency Level: 1 Time taken for tests: 10.020 seconds ... Requests per second: 1.00 [#/sec] (mean) Time per request: 1002.015 [ms] (mean) Time per request: 1002.015 [ms] (mean, across all concurrent requests) Transfer rate: 0.12 [Kbytes/sec] received ...
  • 22. ab -n 10 -c 1 http://127.0.0.1:8080/ This is ApacheBench, Version 2.3 <$Revision: 1178079 $> ... Concurrency Level: 1 Time taken for tests: 10.020 seconds ... Requests per second: 1.00 [#/sec] (mean) Time per request: 1002.015 [ms] (mean) Time per request: 1002.015 [ms] (mean, across all concurrent requests) Transfer rate: 0.12 [Kbytes/sec] received ...
  • 23. ab -n 10 -c 1 http://127.0.0.1:8080/ This is ApacheBench, Version 2.3 <$Revision: 1178079 $> ... Concurrency Level: 1 Time taken for tests: 10.020 seconds ... Requests per second: 1.00 [#/sec] (mean) Time per request: 1002.015 [ms] (mean) Time per request: 1002.015 [ms] (mean, across all concurrent requests) Transfer rate: 0.12 [Kbytes/sec] received ...
  • 24. ab -n 10 -c 1 http://127.0.0.1:8080/ This is ApacheBench, Version 2.3 <$Revision: 1178079 $> ... Concurrency Level: 1 Time taken for tests: 10.020 seconds ... Requests per second: 1.00 [#/sec] (mean) Time per request: 1002.015 [ms] (mean) Time per request: 1002.015 [ms] (mean, across all concurrent requests) Transfer rate: 0.12 [Kbytes/sec] received ...
  • 25. ab -n 10 -c 1 http://127.0.0.1:8080/ This is ApacheBench, Version 2.3 <$Revision: 1178079 $> ... Concurrency Level: 1 Time taken for tests: 10.020 seconds ... Requests per second: 1.00 [#/sec] (mean) Time per request: 1002.015 [ms] (mean) Time per request: 1002.015 [ms] (mean, across all concurrent requests) Transfer rate: 0.12 [Kbytes/sec] received ...
  • 26. Browser Browser Browser Browser Browser Browser NginX, HAProxy Passenger, Unicorn
  • 28. Browser Browser Browser Browser Browser Browser NginX, HAProxy Passenger, Unicorn (CoW GC - REE or MRI 2)
  • 29.
  • 30. Ruby Enterprise Edition 1.8.7 Copy on Write patched (about to be deprecated) mark and sweep GC Ruby 1.9.2 (current) mark and sweep GC Ruby 1.9.3 (transitioning) Lazy Sweep GC Copy on Write compatible Ruby 2.0 (future) Bitmap Marking GC
  • 31. Ruby Enterprise Edition 1.8.7 Copy on Write patched (about to be deprecated) mark and sweep GC Ruby 1.9.2 (current) mark and sweep GC Ruby 1.9.3 (transitioning) Lazy Sweep GC Copy on Write compatible Ruby 2.0 (future) Bitmap Marking GC
  • 32. Ruby Enterprise Edition 1.8.7 Copy on Write patched (about to be deprecated) mark and sweep GC Ruby 1.9.2 (current) mark and sweep GC Ruby 1.9.3 (transitioning) Lazy Sweep GC Copy on Write compatible Ruby 2.0 (future) Bitmap Marking GC
  • 33. Ruby Enterprise Edition 1.8.7 Copy on Write patched (about to be deprecated) mark and sweep GC Ruby 1.9.2 (current) mark and sweep GC Ruby 1.9.3 (transitioning) Lazy Sweep GC Copy on Write compatible Ruby 2.0 (future) Bitmap Marking GC
  • 34. Browser Browser Browser Browser NginX, HAProxy Passenger, Unicorn
  • 35. Browser Browser Browser Browser NginX, HAProxy Passenger, Unicorn Memcached
  • 36. Browser Browser Browser Browser Varnish NginX, HAProxy Passenger, Unicorn Memcached
  • 37. Browser Browser Browser Browser Varnish NginX, HAProxy Passenger, Unicorn Resque Memcached
  • 38. Browser Browser Browser Browser Varnish NginX, HAProxy Passenger, Unicorn Resque Memcached
  • 40.
  • 41. Notifications and Events in general Online Gaming Chatting and Presence Collaborative Applications Advanced and more Interactive UI
  • 42. (function poll(){ $.ajax({ url: "server", success: function(data){ // do something with the received ‘data’ //Setup the next poll recursively poll(); }, dataType: "json"}); })();
  • 43. (function poll(){ setTimeout(function(){ $.ajax({ url: "server", success: function(data){ // do something with the received ‘data’ //Setup the next poll recursively poll(); }, dataType: "json"}); }, 5000); })();
  • 44.
  • 45. Cross Frame communication HTTP Polling (Ajax) Liveconnect (Java applets, Flash socket) Long Polling Comet & HTTP Streaming (ex. forever frame/chunked encode)
  • 46.
  • 47.
  • 48. W3C/IETF Standard - RFC 6455 (12/2011) Full duplex persistent communication channel Less overhead than HTTP (down to 2 bytes per frame) No latency (no reconnections) No polling overhead (on demand) “Upgrades” HTTP, uses 80/443 (kind of friendly to existing proxies)
  • 49. <script type="text/javascript"> var ws = new WebSocket("ws://example.com:10081/"); </script>
  • 50. <script type="text/javascript"> var ws = new WebSocket("ws://example.com:10081/"); ws.onopen = function() { ws.send("Hello"); // Sends a message. }; ws.onmessage = function(e) { // Receives a message. alert(e.data); }; ws.onclose = function() { alert("closed"); }; </script>
  • 51.
  • 52. Protocol IE Firefox Chrome Safari Opera hixie-75 4 5 hixie-76 4 6 5.0.1 11 hybi-00 (disabled) (disabled) hybi-06 HTML5 Labs dev hybi-07 6 hybi-09 HTML5 Labs hybi-10 IE 10 7 14 RFC 6455 11 16
  • 53. POLYFILL/FALLBACK (web-socket-js)
  • 54. <script type="text/javascript" src="swfobject.js"></script> <script type="text/javascript" src="web_socket.js"></script> <script type="text/javascript"> // Let the library know where WebSocketMain.swf is: WEB_SOCKET_SWF_LOCATION = "WebSocketMain.swf"; var ws = new WebSocket("ws://example.com:10081/"); ws.onopen = function() { ws.send("Hello"); // Sends a message. }; ws.onmessage = function(e) { // Receives a message. alert(e.data); }; ws.onclose = function() { alert("closed"); }; </script>
  • 55. <script type="text/javascript" src="swfobject.js"></script> <script type="text/javascript" src="web_socket.js"></script> <script type="text/javascript"> // Let the library know where WebSocketMain.swf is: WEB_SOCKET_SWF_LOCATION = "WebSocketMain.swf"; var ws = new WebSocket("ws://example.com:10081/"); ws.onopen = function() { ws.send("Hello"); // Sends a message. }; ws.onmessage = function(e) { // Receives a message. alert(e.data); }; ws.onclose = function() { alert("closed"); }; </script>
  • 56. <script type="text/javascript" src="swfobject.js"></script> <script type="text/javascript" src="web_socket.js"></script> <script type="text/javascript"> // Let the library know where WebSocketMain.swf is: WEB_SOCKET_SWF_LOCATION = "WebSocketMain.swf"; var ws = new WebSocket("ws://example.com:10081/"); ws.onopen = function() { ws.send("Hello"); // Sends a message. }; ws.onmessage = function(e) { // Receives a message. alert(e.data); }; ws.onclose = function() { alert("closed"); }; </script>
  • 57. <script type="text/javascript" src="swfobject.js"></script> <script type="text/javascript" src="web_socket.js"></script> <script type="text/javascript"> // Let the library know where WebSocketMain.swf is: WEB_SOCKET_SWF_LOCATION = "WebSocketMain.swf"; var ws = new WebSocket("ws://example.com:10081/"); ws.onopen = function() { ws.send("Hello"); // Sends a message. }; ws.onmessage = function(e) { // Receives a message. alert(e.data); }; ws.onclose = function() { alert("closed"); }; </script>
  • 58. <script type="text/javascript" src="swfobject.js"></script> <script type="text/javascript" src="web_socket.js"></script> <script type="text/javascript"> // Let the library know where WebSocketMain.swf is: WEB_SOCKET_SWF_LOCATION = "WebSocketMain.swf"; var ws = new WebSocket("ws://example.com:10081/"); ws.onopen = function() { ws.send("Hello"); // Sends a message. }; ws.onmessage = function(e) { // Receives a message. alert(e.data); }; ws.onclose = function() { alert("closed"); }; </script>
  • 59. Client: kind of OK Server: what do do?
  • 61. Reactor Pattern (Eventmachine)
  • 62.
  • 63. synchronous I/O non-blocking synchronous I/O non-blocking asynchronous I/0
  • 64. Wait Events (I/O, timers) Main Loop Notifies Event (main thread) Handlers
  • 65.
  • 66. select poll
  • 67. select poll epoll kqueue IOCP
  • 68. libevent libev select poll epoll kqueue IOCP
  • 69. Tornado Twisted libevent libev select poll epoll kqueue IOCP
  • 70. Tornado Twisted Node.js libevent libev select poll epoll kqueue IOCP
  • 71. Tornado Cool.io Twisted Node.js libevent libev select poll epoll kqueue IOCP
  • 72. Tornado Cool.io Twisted Node.js libevent libev EventMachine select poll epoll kqueue IOCP
  • 73. Tornado Cool.io Goliath Twisted Node.js Thin libevent libev EventMachine select poll epoll kqueue IOCP
  • 74. require 'rubygems' require 'rack' class Test def call(env) sleep 1 # on purpose, simulating a blocking operation [200, {"Content-Type" => "text/plain"}, ["Hello World!"]] end end Rack::Handler::Thin.run Test.new
  • 75. require 'rubygems' require 'rack' class Test def call(env) EM.defer do sleep 1 # CPU bound, throw to thread-pool (cheating) end [200, {"Content-Type" => "text/plain"}, ["Hello World!"]] end end Rack::Handler::Thin.run Test.new
  • 76. require 'rubygems' require 'rack' class Test def call(env) EM.defer do sleep 1 # CPU bound, throw to thread-pool (cheating) end [200, {"Content-Type" => "text/plain"}, ["Hello World!"]] end end Rack::Handler::Thin.run Test.new
  • 77. require 'rubygems' require 'rack' class Test def call(env) EM.defer do sleep 1 # CPU bound, throw to thread-pool (cheating) end [200, {"Content-Type" => "text/plain"}, ["Hello World!"]] end end Rack::Handler::Thin.run Test.new
  • 78. ab -n 10 -c 1 http://127.0.0.1:8080/ This is ApacheBench, Version 2.3 <$Revision: 1178079 $> ... Concurrency Level: 1 Time taken for tests: 0.003 seconds ... Requests per second: 3219.58 [#/sec] (mean) Time per request: 0.311 [ms] (mean) Time per request: 0.311 [ms] (mean, across all concurrent requests) Transfer rate: 380.44 [Kbytes/sec] received ...
  • 79. ab -n 10 -c 1 http://127.0.0.1:8080/ This is ApacheBench, Version 2.3 <$Revision: 1178079 $> ... Concurrency Level: 1 Time taken for tests: 0.003 seconds ... Requests per second: 3219.58 [#/sec] (mean) Time per request: 0.311 [ms] (mean) Time per request: 0.311 [ms] (mean, across all concurrent requests) Transfer rate: 380.44 [Kbytes/sec] received ...
  • 80. ab -n 10 -c 1 http://127.0.0.1:8080/ This is ApacheBench, Version 2.3 <$Revision: 1178079 $> ... Concurrency Level: 1 Time taken for tests: 0.003 seconds ... Requests per second: 3219.58 [#/sec] (mean) Time per request: 0.311 [ms] (mean) Time per request: 0.311 [ms] (mean, across all concurrent requests) Transfer rate: 380.44 [Kbytes/sec] received ...
  • 81. ab -n 10 -c 1 http://127.0.0.1:8080/ This is ApacheBench, Version 2.3 <$Revision: 1178079 $> ... Concurrency Level: 1 Time taken for tests: 0.003 seconds ... Requests per second: 3219.58 [#/sec] (mean) Time per request: 0.311 [ms] (mean) Time per request: 0.311 [ms] (mean, across all concurrent requests) Transfer rate: 380.44 [Kbytes/sec] received ...
  • 82. ab -n 10 -c 1 http://127.0.0.1:8080/ This is ApacheBench, Version 2.3 <$Revision: 1178079 $> ... Concurrency Level: 1 Time taken for tests: 0.003 seconds ... Requests per second: 3219.58 [#/sec] (mean) Time per request: 0.311 [ms] (mean) Time per request: 0.311 [ms] (mean, across all concurrent requests) Transfer rate: 380.44 [Kbytes/sec] received ...
  • 83. ab -n 10 -c 1 http://127.0.0.1:8080/ This is ApacheBench, Version 2.3 <$Revision: 1178079 $> #ZOMG! ... Concurrency Level: 1 Time taken for tests: 0.003 seconds ... Requests per second: 3219.58 [#/sec] (mean) Time per request: 0.311 [ms] (mean) Time per request: 0.311 [ms] (mean, across all concurrent requests) Transfer rate: 380.44 [Kbytes/sec] received ...
  • 84. ab -n 10 -c 10 http://127.0.0.1:8080/ This is ApacheBench, Version 2.3 <$Revision: 1178079 $> ... Concurrency Level: 10 Time taken for tests: 0.002 seconds ... Requests per second: 5211.05 [#/sec] (mean) Time per request: 1.919 [ms] (mean) Time per request: 0.192 [ms] (mean, across all concurrent requests) Transfer rate: 615.76 [Kbytes/sec] received ...
  • 85.
  • 86. Block Non-Block Total Time 10 sec 0.0001 sec Requests per Second 1 + 8000
  • 87. Block Non-Block Total Time 10 sec 0.0001 sec Requests per Second 1 + 8000
  • 88. Block Non-Block Total Time 10 sec 0.0001 sec Requests per Second 1 + 8000
  • 89. “Tick” Timers #add_timer #add_periodic_timer Reactor Loop Blocking Tasks (Eventmachine) #defer #next_tick
  • 90. require 'rubygems' # or use Bundler.setup require 'eventmachine' class EchoServer < EM::Connection def receive_data(data) if data.strip =~ /[exit|quit]$/i EM.stop else send_data("Repeating: #{data}") end end end
  • 91. require 'rubygems' # or use Bundler.setup require 'eventmachine' class EchoServer < EM::Connection def receive_data(data) if data.strip =~ /[exit|quit]$/i EM.stop else send_data("Repeating: #{data}") end end end EventMachine.run do # hit Control + C to stop Signal.trap("INT") { EM.stop } Signal.trap("TERM") { EM.stop } EM.start_server("0.0.0.0", 10000, EchoServer) end
  • 92. $ telnet localhost 10000 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Hello World
  • 93. $ telnet localhost 10000 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Hello World Repeating: Hello World
  • 94. $ telnet localhost 10000 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Hello World Repeating: Hello World Play again, Sam
  • 95. $ telnet localhost 10000 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Hello World Repeating: Hello World Play again, Sam Repeating: Play again, Sam
  • 96. $ telnet localhost 10000 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Hello World Repeating: Hello World Play again, Sam Repeating: Play again, Sam quit .
  • 97. $ telnet localhost 10000 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Hello World Repeating: Hello World Play again, Sam Repeating: Play again, Sam quit Connection closed by foreign host.
  • 98. require 'rubygems' require 'eventmachine' EM.run do # ... main reactor loop EM.stop # stop the main loop and exit end
  • 101. require 'rubygems' require 'eventmachine' EM.run do EM.defer do sleep 3 puts 1 end EM.add_timer(1) do puts 2 EM.add_timer(1) do puts 3 end end puts 4 end
  • 103.
  • 104. var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World'); }).listen(9876);
  • 105. ab -n 1000 -c 5 http://127.0.0.1:9876/ This is ApacheBench, Version 2.3 <$Revision: 1178079 $> ... Concurrency Level: 5 Time taken for tests: 0.124 seconds ... Requests per second: 8035.36 [#/sec] (mean) Time per request: 0.622 [ms] (mean) Time per request: 0.124 [ms] (mean, across all concurrent requests) Transfer rate: 588.53 [Kbytes/sec] received ...
  • 106. require 'rubygems' require 'rack' Rack::Handler::Thin.run Proc.new { [200, {"Content-Type" => "text/plain"}, ["Hello World!"]] }
  • 107. ab -n 1000 -c 5 http://127.0.0.1:8080/ This is ApacheBench, Version 2.3 <$Revision: 1178079 $> ... Concurrency Level: 5 Time taken for tests: 0.121 seconds .. Requests per second: 8239.06 [#/sec] (mean) Time per request: 0.607 [ms] (mean) Time per request: 0.121 [ms] (mean, across all concurrent requests) Transfer rate: 973.56 [Kbytes/sec] received ...
  • 108.
  • 109. Node.js Ruby libev Eventmachine, Cool.io Google V8 MRI, JRuby, Rubinius Less Resources, Faster More Resources, Slightly Processing slower processing callbacks only Threads, Fibers, Callbacks
  • 110. Node.js Ruby libev Eventmachine, Cool.io Google V8 MRI, JRuby, Rubinius Less Resources, Faster More Resources, Slightly Processing slower processing callbacks only Threads, Fibers, Callbacks
  • 111. Node.js Ruby libev Eventmachine, Cool.io Google V8 MRI, JRuby, Rubinius Less Resources, Faster More Resources, Slightly Processing slower processing callbacks only Threads, Fibers, Callbacks
  • 112. Node.js Ruby libev Eventmachine, Cool.io Google V8 MRI, JRuby, Rubinius Less Resources, Faster More Resources, Slightly Processing slower processing callbacks only Threads, Fibers, Callbacks
  • 113. Node.js Ruby libev Eventmachine, Cool.io Google V8 MRI, JRuby, Rubinius Less Resources, Faster More Resources, Slightly Processing slower processing callbacks only Threads, Fibers, Callbacks
  • 115. require "rubygems" require 'eventmachine' require 'em-websocket' config = {:host => "0.0.0.0", :port => 8080, :debug => true} EM::WebSocket.start(config) do |ws| ws.onopen { ws.send "Welcome!"} ws.onmessage { |msg| ws.send "Sending Pong: #{msg}" } ws.onclose { puts "connection closed" } ws.onerror { |e| puts "Error: #{e.message}" } end
  • 116. Caveats in Callback Driven Development
  • 117. fs.rename('/tmp/hello', '/tmp/world', function (err) { if (err) throw err; console.log('renamed complete'); }); fs.stat('/tmp/world', function (err, stats) { if (err) throw err; console.log('stats: ' + JSON.stringify(stats)); });
  • 118. fs.rename('/tmp/hello', '/tmp/world', function (err) { if (err) throw err; fs.stat('/tmp/world', function (err, stats) { if (err) throw err; console.log('stats: ' + JSON.stringify(stats)); }); });
  • 119. EM.run do page = EM::HttpRequest.new(@url1).get page.errback do puts "Site is down! terminate?" end page.callback do about = EM::HttpRequest.new(@url2).get about.callback do # callback nesting, ad infinitum end about.errback do # error-handling code end end end
  • 121. Ruby 1.9 Fibers to the rescue!
  • 122. number_generator = Fiber.new do start = 0 loop do start += 1 Fiber.yield(start) end end
  • 123. number_generator = Fiber.new do start = 0 loop do start += 1 Fiber.yield(start) end end > number_generator.resume => 1
  • 124. number_generator = Fiber.new do start = 0 loop do start += 1 Fiber.yield(start) end end > number_generator.resume => 1 > number_generator.resume => 2
  • 125. number_generator = Fiber.new do start = 0 loop do start += 1 Fiber.yield(start) end end > number_generator.resume => 1 > number_generator.resume => 2 > number_generator.resume => 3
  • 126.
  • 127. Less expensive than Threads cooperative vs preemptive multitasking developer controls scheduling no need to have mutexes, no shared data coroutines / can be implemented with continuations
  • 128. Less expensive than Threads cooperative vs preemptive multitasking developer controls scheduling no need to have mutexes, no shared data coroutines / can be implemented with continuations
  • 129. Less expensive than Threads cooperative vs preemptive multitasking developer controls scheduling no need to have mutexes, no shared data coroutines / can be implemented with continuations
  • 130. Less expensive than Threads cooperative vs preemptive multitasking developer controls scheduling no need to have mutexes, no shared data coroutines / can be implemented with continuations
  • 131. Less expensive than Threads cooperative vs preemptive multitasking developer controls scheduling no need to have mutexes, no shared data coroutines / can be implemented with continuations
  • 132. EM.run do page = EM::HttpRequest.new(@url1).get page.errback do puts "Site is down! terminate?" end page.callback do about = EM::HttpRequest.new(@url2).get about.callback do # callback nesting, ad infinitum end about.errback do # error-handling code end end end
  • 133. page = http_get(@url1) puts "Fetched page: #{page.response_header.status}" if page page = http_get(@url2) puts "Fetched page 2: #{page.response_header.status}" end
  • 134. def http_get(url) f = Fiber.current http = EM::HttpRequest.new(url).get http.callback{ f.resume(http) } http.errback { f.resume(http) } return Fiber.yield end EM.run do Fiber.new do page = http_get(@url1) puts "Fetched page: #{page.response_header.status}" if page page = http_get(@url2) puts "Fetched page 2: #{page.response_header.status}" end do.resume end
  • 135. def http_get(url) f = Fiber.current http = EM::HttpRequest.new(url).get http.callback{ f.resume(http) } http.errback { f.resume(http) } return Fiber.yield end EM.run do Fiber.new do page = http_get(@url1) puts "Fetched page: #{page.response_header.status}" if page page = http_get(@url2) puts "Fetched page 2: #{page.response_header.status}" end do.resume end
  • 136. def http_get(url) f = Fiber.current http = EM::HttpRequest.new(url).get http.callback{ f.resume(http) } http.errback { f.resume(http) } return Fiber.yield end EM.run do Fiber.new do page = http_get(@url1) puts "Fetched page: #{page.response_header.status}" if page page = http_get(@url2) puts "Fetched page 2: #{page.response_header.status}" end do.resume end
  • 137. def http_get(url) f = Fiber.current http = EM::HttpRequest.new(url).get http.callback{ f.resume(http) } http.errback { f.resume(http) } return Fiber.yield end EM.run do Fiber.new do page = http_get(@url1) puts "Fetched page: #{page.response_header.status}" if page page = http_get(@url2) puts "Fetched page 2: #{page.response_header.status}" end do.resume end
  • 138. def http_get(url) f = Fiber.current http = EM::HttpRequest.new(url).get http.callback{ f.resume(http) } http.errback { f.resume(http) } return Fiber.yield end EM.run do Fiber.new do page = http_get(@url1) puts "Fetched page: #{page.response_header.status}" if page page = http_get(@url2) puts "Fetched page 2: #{page.response_header.status}" end do.resume end
  • 139. def http_get(url) f = Fiber.current http = EM::HttpRequest.new(url).get http.callback{ f.resume(http) } http.errback { f.resume(http) } return Fiber.yield end EM.run do Fiber.new do page = http_get(@url1) puts "Fetched page: #{page.response_header.status}" if page page = http_get(@url2) puts "Fetched page 2: #{page.response_header.status}" end do.resume end
  • 140. def http_get(url) f = Fiber.current http = EM::HttpRequest.new(url).get http.callback{ f.resume(http) } http.errback { f.resume(http) } return Fiber.yield end EM.run do Fiber.new do page = http_get(@url1) puts "Fetched page: #{page.response_header.status}" if page page = http_get(@url2) puts "Fetched page 2: #{page.response_header.status}" end do.resume end
  • 142. EM.synchrony do page = EM::HttpRequest.new("http://www.google.com").get puts "Look Ma! No callbacks! Fetched page: #{page}" EM.stop end # old way EM.run do page = EM::HttpRequest.new("http://www.google.com").get page.callback do puts "Lame ... Fetched page: #{page}" EM.stop end end
  • 144. require 'goliath' require 'yajl' G = Goliath::Rack # don’t to this, just to fit in this slide :-) class Echo < Goliath::API use G::Render, 'json' # auto-negotiate response format use G::Params # parse & merge query and body parameters use G::Validation::RequiredParam, {:key => 'echo'} def process_request logger.info "Processing request" {response: env.params['echo']} end def response(env) [200, {}, process_request] end end
  • 145. $ ruby echo.rb -p 9001
  • 146. $ ruby echo.rb -p 9001 $ curl http://localhost:9001/ {"error":"Echo identifier missing"}
  • 147. $ ruby echo.rb -p 9001 $ curl http://localhost:9001/ {"error":"Echo identifier missing"} $ curl http://localhost:9001?echo=Hello%20World {"response":"Hello World"}
  • 148.
  • 149. Web App Server and App Framework Fully asynchronous using Eventmachine Lightweight and High Performance (+ 3k req/s in 1 process) Rack aware (but not 100% Rack compatible) Fibers with EM-Synchrony for easier development
  • 150. Recap so far ...
  • 151.
  • 152. Ruby can using Reactors to massively scale Good contender to Node.js-style (getting better) One single Ruby process can handle thousands of concurrent requests Web browsers got smarter with Websockets Ruby implements Websocket support
  • 153. Pusher
  • 154. Browser Persistent connection! async Rails App Eventmachine App Resque Queues sync
  • 155. Browser Persistent connection! async Rails App Eventmachine App Resque Queues sync
  • 157. <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/ jquery.min.js"></script> <script src="http://js.pusher.com/1.11/pusher.min.js"></script> <script> var pusher = new Pusher('7114e...c318e'); var channel = pusher.subscribe('demo-channel'); channel.bind('create', function(message) { var elem = $("#" + message.elem_id); if (elem) elem.remove(); var html = "<li id='" + message.elem_id + "'>" + message.elem_id + " - " + message.value + "</li>"; $("#list").append(html); }); channel.bind('delete', function(message) { var elem = $("#" + message.elem_id); if (elem) elem.remove(); }); </script>
  • 158. require 'rubygems' require 'pusher' Pusher.app_id = '14909' Pusher.key = '7114e...c318e' Pusher.secret = '25aa7...3d49c' ('a'..'z').each do |letter| doc = { :elem_id => letter, :value => "Letter: #{letter}"} Pusher['demo-channel'].trigger('create', doc) end
  • 159. time ruby pusher_sync.rb real 0m14.585s user 0m0.583s sys 0m0.105s
  • 160. require 'rubygems' require 'pusher' require 'eventmachine' Pusher.app_id = '14909' Pusher.key = '7114e...c318e' Pusher.secret = '25aa7...d49c' EM.run do EM::Iterator.new("a".."z").each do |letter, iter| doc = { :elem_id => elem_id, :value => "Letter: #{letter}" } pusher = Pusher['demo-channel'].trigger_async('create', doc) pusher.callback { EM.stop if letter == 'z' } pusher.errback { |error| EM.stop if letter == 'z' } iter.next end end
  • 161. require 'rubygems' require 'pusher' require 'eventmachine' Pusher.app_id = '14909' Pusher.key = '7114e...c318e' Pusher.secret = '25aa7...d49c' EM.run do EM::Iterator.new("a".."z").each do |letter, iter| doc = { :elem_id => elem_id, :value => "Letter: #{letter}" } pusher = Pusher['demo-channel'].trigger_async('create', doc) pusher.callback { EM.stop if letter == 'z' } pusher.errback { |error| EM.stop if letter == 'z' } iter.next end end
  • 162. require 'rubygems' require 'pusher' require 'eventmachine' Pusher.app_id = '14909' Pusher.key = '7114e...c318e' Pusher.secret = '25aa7...d49c' EM.run do EM::Iterator.new("a".."z").each do |letter, iter| doc = { :elem_id => elem_id, :value => "Letter: #{letter}" } pusher = Pusher['demo-channel'].trigger_async('create', doc) pusher.callback { EM.stop if letter == 'z' } pusher.errback { |error| EM.stop if letter == 'z' } iter.next end end
  • 163. time ruby pusher_async.rb real 0m1.129s user 0m0.649s sys 0m0.063s
  • 164. pusher.connection.bind('connected', function() { alert("You're up!") }); pusher.connection.bind('connecting_in', function(delay) { alert("Retrying in " + delay + " seconds.") }); pusher.connection.bind('failed', function() { document.write("Not able to connect.") });
  • 165.
  • 166. Private Channels Encryption Authentication Presence Events
  • 167.
  • 168. Total API requests (11/02/2011) (day has 86.400 seconds)
  • 169. 13.969.264 Total API requests (11/02/2011) (day has 86.400 seconds)
  • 170. Amount of messages sent to clients since launch (11/02/2011)
  • 171. 35.552.810.379 Amount of messages sent to clients since launch (11/02/2011)
  • 172. average latency (excluding internet - 11/02/2011)
  • 173. < 10ms average latency (excluding internet - 11/02/2011)
  • 175.
  • 176. CGI model is difficult to scale Multi-processes vs multi-threads vs Reactors HTTP 5 WebSockets is hot! Eventmachine is great! Fibers vs “callback spaghetti” Try out Pusher!
  • 177. CGI model is difficult to scale Multi-processes vs multi-threads vs Reactors HTTP 5 WebSockets is hot! Eventmachine is great! Fibers vs “callback spaghetti” Try out Pusher!
  • 178. CGI model is difficult to scale Multi-processes vs multi-threads vs Reactors HTTP 5 WebSockets is hot! Eventmachine is great! Fibers vs “callback spaghetti” Try out Pusher!
  • 179. CGI model is difficult to scale Multi-processes vs multi-threads vs Reactors HTTP 5 WebSockets is hot! Eventmachine is great! Fibers vs “callback spaghetti” Try out Pusher!
  • 180. CGI model is difficult to scale Multi-processes vs multi-threads vs Reactors HTTP 5 WebSockets is hot! Eventmachine is great! Fibers vs “callback spaghetti” Try out Pusher!
  • 181. CGI model is difficult to scale Multi-processes vs multi-threads vs Reactors HTTP 5 WebSockets is hot! Eventmachine is great! Fibers vs “callback spaghetti” Try out Pusher!
  • 182. Ilya Grigorik (igvita)
  • 183.
  • 184. PostRank (acquired by Google!) EM-Synchrony, Goliath Google SPDY research
  • 186.
  • 187. Rev (later Cool.io), Revactor Reia (Ruby syntax over Erlang, replaced by Elixir) Celluloid (Threads abstraction to Actors) (Mark Perham used to create Sidekiq)
  • 188. Ruby is very flexible
  • 190. Browser Browser Browser Browser Browser Browser NginX, HAProxy Passenger, Unicorn
  • 191. Browser Browser Browser Browser Browser Browser NginX, HAProxy JRuby - TorqueBox, Trinidad (multiple concurrent native threads)
  • 192.
  • 193. Native threads Ruby 1.9.x (extensions can release the GIL) Native threads JRuby (no GIL) Native threads Rubinius (no GIL check out the Puma webserver)
  • 194. Native threads Ruby 1.9.x (extensions can release the GIL) Native threads JRuby (no GIL) Native threads Rubinius (no GIL check out the Puma webserver)
  • 195. Native threads Ruby 1.9.x (extensions can release the GIL) Native threads JRuby (no GIL) Native threads Rubinius (no GIL check out the Puma webserver)
  • 196.
  • 197.
  • 198.
  • 199. Большое спасибо www.codeminer.com.br www.akitaonrails.com @akitaonrails