199
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

Understanding the Rails web model and scalability options

  • Upload
    toster

  • View
    1.494

  • Download
    2

Embed Size (px)

DESCRIPTION

Rails стал отличным ответом на требования многих лет опыта использования классической процессной модели веб-запросов. Такая модель все еще является наиболее надежной и простой для понимания и контроля. Но новое поколение высокодинамичных и интерактивных веб приложений требует принципиально новых требований к масштабированию. Одним из ответов на такие требования может стать сервис Pusher.com, который, в числе прочих вариантов решений, будет рассмотрен в этом докладе

Citation preview

Page 1: Understanding the Rails web model and scalability options

Genius is the gold in the mine; talent is the miner who works and brings it out.Lady Marguerite Blessington

“”

Donets BasinCoal Mine-Ukraine

Page 2: Understanding the Rails web model and scalability options

Genius is the gold in the mine; talent is the miner who works and brings it out.Lady Marguerite Blessington

“”

Donets BasinCoal Mine-Ukraine

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

Page 3: Understanding the Rails web model and scalability options

доброе утро

Page 4: Understanding the Rails web model and scalability options

Fabio Akita, Co-Founder @CodeMiner42

Page 5: Understanding the Rails web model and scalability options

“Off-centered software for off-centered people”

Fabio Akita, Co-Founder @CodeMiner42

Page 6: Understanding the Rails web model and scalability options
Page 7: Understanding the Rails web model and scalability options
Page 8: Understanding the Rails web model and scalability options

Understandingthe Rails Web Modeland Scalability Options

Page 9: Understanding the Rails web model and scalability options

?

Page 10: Understanding the Rails web model and scalability options
Page 11: Understanding the Rails web model and scalability options
Page 12: Understanding the Rails web model and scalability options

rails new app

Page 13: Understanding the Rails web model and scalability options
Page 14: Understanding the Rails web model and scalability options

somethings don’t change

Page 15: Understanding the Rails web model and scalability options
Page 16: Understanding the Rails web model and scalability options

CGI

Page 17: Understanding the Rails web model and scalability options

1 request blocks 1 process

Page 18: Understanding the Rails web model and scalability options

require 'rubygems'require 'rack'

class Test def call(env)

sleep 1 # on purpose, simulating a blocking operation

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

Rack::Handler::Thin.run Test.new

Page 19: Understanding the Rails web model and scalability options

require 'rubygems'require 'rack'

class Test def call(env)

sleep 1 # on purpose, simulating a blocking operation

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

Rack::Handler::Thin.run Test.new

Page 20: Understanding the Rails web model and scalability options

$ 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

Page 21: Understanding the Rails web model and scalability options

ab -n 10 -c 1 http://127.0.0.1:8080/

This is ApacheBench, Version 2.3 <$Revision: 1178079 $>...Concurrency Level: 1Time 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...

Page 22: Understanding the Rails web model and scalability options

ab -n 10 -c 1 http://127.0.0.1:8080/

This is ApacheBench, Version 2.3 <$Revision: 1178079 $>...Concurrency Level: 1Time 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...

Page 23: Understanding the Rails web model and scalability options

ab -n 10 -c 1 http://127.0.0.1:8080/

This is ApacheBench, Version 2.3 <$Revision: 1178079 $>...Concurrency Level: 1Time 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...

Page 24: Understanding the Rails web model and scalability options

ab -n 10 -c 1 http://127.0.0.1:8080/

This is ApacheBench, Version 2.3 <$Revision: 1178079 $>...Concurrency Level: 1Time 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...

Page 25: Understanding the Rails web model and scalability options

ab -n 10 -c 1 http://127.0.0.1:8080/

This is ApacheBench, Version 2.3 <$Revision: 1178079 $>...Concurrency Level: 1Time 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...

Page 26: Understanding the Rails web model and scalability options

Passenger, Unicorn

NginX, HAProxy

Browser Browser Browser Browser Browser Browser

Page 27: Understanding the Rails web model and scalability options

Optimize

Page 28: Understanding the Rails web model and scalability options

Passenger, Unicorn (CoW GC - REE or MRI 2)

NginX, HAProxy

Browser Browser Browser Browser Browser Browser

Page 29: Understanding the Rails web model and scalability options
Page 30: Understanding the Rails web model and scalability options

Ruby Enterprise Edition 1.8.7(about to be deprecated)

Copy on Write patchedmark and sweep GC

Ruby 1.9.2 (current) mark and sweep GC

Ruby 1.9.3 (transitioning) Lazy Sweep GC

Ruby 2.0 (future)Copy on Write compatible

Bitmap Marking GC

Page 31: Understanding the Rails web model and scalability options

Ruby Enterprise Edition 1.8.7(about to be deprecated)

Copy on Write patchedmark and sweep GC

Ruby 1.9.2 (current) mark and sweep GC

Ruby 1.9.3 (transitioning) Lazy Sweep GC

Ruby 2.0 (future)Copy on Write compatible

Bitmap Marking GC

Page 32: Understanding the Rails web model and scalability options

Ruby Enterprise Edition 1.8.7(about to be deprecated)

Copy on Write patchedmark and sweep GC

Ruby 1.9.2 (current) mark and sweep GC

Ruby 1.9.3 (transitioning) Lazy Sweep GC

Ruby 2.0 (future)Copy on Write compatible

Bitmap Marking GC

Page 33: Understanding the Rails web model and scalability options

Ruby Enterprise Edition 1.8.7(about to be deprecated)

Copy on Write patchedmark and sweep GC

Ruby 1.9.2 (current) mark and sweep GC

Ruby 1.9.3 (transitioning) Lazy Sweep GC

Ruby 2.0 (future)Copy on Write compatible

Bitmap Marking GC

Page 34: Understanding the Rails web model and scalability options

Passenger, Unicorn

NginX, HAProxy

Browser Browser Browser Browser

Page 35: Understanding the Rails web model and scalability options

Passenger, Unicorn

NginX, HAProxy

Browser Browser Browser Browser

Memcached

Page 36: Understanding the Rails web model and scalability options

Passenger, Unicorn

NginX, HAProxy

Browser Browser Browser Browser

Memcached

Varnish

Page 37: Understanding the Rails web model and scalability options

Passenger, Unicorn

NginX, HAProxy

Browser Browser Browser Browser

Memcached

Varnish

Resque

Page 38: Understanding the Rails web model and scalability options

Passenger, Unicorn

NginX, HAProxy

Browser Browser Browser Browser

Memcached

Varnish

Resque

Page 39: Understanding the Rails web model and scalability options

Too Long or Periodic Polling

Page 40: Understanding the Rails web model and scalability options
Page 41: Understanding the Rails web model and scalability options

Notifications and Events in general

Online Gaming

Chatting and Presence

Collaborative Applications

Advanced and more Interactive UI

Page 42: Understanding the Rails web model and scalability options

(function poll(){

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

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

})();

Page 43: Understanding the Rails web model and scalability options

(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);})();

Page 44: Understanding the Rails web model and scalability options
Page 45: Understanding the Rails web model and scalability options

Cross Frame communication

HTTP Polling (Ajax)

Liveconnect (Java applets, Flash socket)

Long Polling

Comet & HTTP Streaming(ex. forever frame/chunked encode)

Page 46: Understanding the Rails web model and scalability options
Page 47: Understanding the Rails web model and scalability options
Page 48: Understanding the Rails web model and scalability options

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)

Page 49: Understanding the Rails web model and scalability options

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

</script>

Page 50: Understanding the Rails web model and scalability options

<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>

Page 51: Understanding the Rails web model and scalability options
Page 52: Understanding the Rails web model and scalability options

Protocol IE Firefox Chrome Safari Opera

hixie-75 4 5

hixie-76hybi-00

4(disabled)

6 5.0.1 11(disabled)

hybi-06 HTML5 Labs dev

hybi-07 6

hybi-09 HTML5 Labs

hybi-10 IE 10 7 14

RFC 6455 11 16

Page 53: Understanding the Rails web model and scalability options

POLYFILL/FALLBACK(web-socket-js)

Page 54: Understanding the Rails web model and scalability options

<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>

Page 55: Understanding the Rails web model and scalability options

<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>

Page 56: Understanding the Rails web model and scalability options

<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>

Page 57: Understanding the Rails web model and scalability options

<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>

Page 58: Understanding the Rails web model and scalability options

<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>

Page 59: Understanding the Rails web model and scalability options

Client: kind of OKServer: what do do?

Page 60: Understanding the Rails web model and scalability options

Long running requests

Page 61: Understanding the Rails web model and scalability options

Reactor Pattern(Eventmachine)

Page 62: Understanding the Rails web model and scalability options
Page 63: Understanding the Rails web model and scalability options

synchronous I/O

non-blocking synchronous I/O

non-blocking asynchronous I/0

Page 64: Understanding the Rails web model and scalability options

Main Loop(main thread)

Wait Events(I/O, timers)

Notifies Event Handlers

Page 65: Understanding the Rails web model and scalability options
Page 66: Understanding the Rails web model and scalability options

select poll

Page 67: Understanding the Rails web model and scalability options

select poll epoll kqueue IOCP

Page 68: Understanding the Rails web model and scalability options

libevent libev

select poll epoll kqueue IOCP

Page 69: Understanding the Rails web model and scalability options

libevent libev

select poll epoll kqueue IOCP

Twisted

Tornado

Page 70: Understanding the Rails web model and scalability options

libevent libev

select poll epoll kqueue IOCP

Twisted

Tornado

Node.js

Page 71: Understanding the Rails web model and scalability options

libevent libev

select poll epoll kqueue IOCP

Twisted

Tornado

Node.js

Cool.io

Page 72: Understanding the Rails web model and scalability options

libevent libev

select poll epoll kqueue IOCP

EventMachine

Twisted

Tornado

Node.js

Cool.io

Page 73: Understanding the Rails web model and scalability options

libevent libev

select poll epoll kqueue IOCP

EventMachine

Twisted

Tornado

Node.js

Cool.io

Thin

Goliath

Page 74: Understanding the Rails web model and scalability options

require 'rubygems'require 'rack'

class Test def call(env)

sleep 1 # on purpose, simulating a blocking operation

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

Rack::Handler::Thin.run Test.new

Page 75: Understanding the Rails web model and scalability options

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!"]] endend

Rack::Handler::Thin.run Test.new

Page 76: Understanding the Rails web model and scalability options

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!"]] endend

Rack::Handler::Thin.run Test.new

Page 77: Understanding the Rails web model and scalability options

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!"]] endend

Rack::Handler::Thin.run Test.new

Page 78: Understanding the Rails web model and scalability options

ab -n 10 -c 1 http://127.0.0.1:8080/This is ApacheBench, Version 2.3 <$Revision: 1178079 $>...Concurrency Level: 1Time 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...

Page 79: Understanding the Rails web model and scalability options

ab -n 10 -c 1 http://127.0.0.1:8080/This is ApacheBench, Version 2.3 <$Revision: 1178079 $>...Concurrency Level: 1Time 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...

Page 80: Understanding the Rails web model and scalability options

ab -n 10 -c 1 http://127.0.0.1:8080/This is ApacheBench, Version 2.3 <$Revision: 1178079 $>...Concurrency Level: 1Time 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...

Page 81: Understanding the Rails web model and scalability options

ab -n 10 -c 1 http://127.0.0.1:8080/This is ApacheBench, Version 2.3 <$Revision: 1178079 $>...Concurrency Level: 1Time 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...

Page 82: Understanding the Rails web model and scalability options

ab -n 10 -c 1 http://127.0.0.1:8080/This is ApacheBench, Version 2.3 <$Revision: 1178079 $>...Concurrency Level: 1Time 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...

Page 83: Understanding the Rails web model and scalability options

ab -n 10 -c 1 http://127.0.0.1:8080/This is ApacheBench, Version 2.3 <$Revision: 1178079 $>...Concurrency Level: 1Time 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...

#ZOMG!

Page 84: Understanding the Rails web model and scalability options

ab -n 10 -c 10 http://127.0.0.1:8080/This is ApacheBench, Version 2.3 <$Revision: 1178079 $>...Concurrency Level: 10Time 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...

Page 85: Understanding the Rails web model and scalability options
Page 86: Understanding the Rails web model and scalability options

Block Non-Block

Total Time 10 sec 0.0001 sec

Requests per Second 1 + 8000

Page 87: Understanding the Rails web model and scalability options

Block Non-Block

Total Time 10 sec 0.0001 sec

Requests per Second 1 + 8000

Page 88: Understanding the Rails web model and scalability options

Block Non-Block

Total Time 10 sec 0.0001 sec

Requests per Second 1 + 8000

Page 89: Understanding the Rails web model and scalability options

Reactor Loop(Eventmachine)

Timers#add_timer

#add_periodic_timer

Blocking Tasks#defer

#next_tick

“Tick”

Page 90: Understanding the Rails web model and scalability options

require 'rubygems' # or use Bundler.setuprequire 'eventmachine'

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

Page 91: Understanding the Rails web model and scalability options

require 'rubygems' # or use Bundler.setuprequire 'eventmachine'

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

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

Page 92: Understanding the Rails web model and scalability options

$ telnet localhost 10000Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.Hello World

Page 93: Understanding the Rails web model and scalability options

$ telnet localhost 10000Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.Hello WorldRepeating: Hello World

Page 94: Understanding the Rails web model and scalability options

$ telnet localhost 10000Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.Hello WorldRepeating: Hello WorldPlay again, Sam

Page 95: Understanding the Rails web model and scalability options

$ telnet localhost 10000Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.Hello WorldRepeating: Hello WorldPlay again, SamRepeating: Play again, Sam

Page 96: Understanding the Rails web model and scalability options

$ telnet localhost 10000Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.Hello WorldRepeating: Hello WorldPlay again, SamRepeating: Play again, Samquit.

Page 97: Understanding the Rails web model and scalability options

$ telnet localhost 10000Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.Hello WorldRepeating: Hello WorldPlay again, SamRepeating: Play again, SamquitConnection closed by foreign host.

Page 98: Understanding the Rails web model and scalability options

require 'rubygems'require 'eventmachine'

EM.run do # ... main reactor loop EM.stop # stop the main loop and exitend

Page 99: Understanding the Rails web model and scalability options

require 'rubygems'require 'eventmachine'

EM.run do puts 1 puts 2 puts 3end

Page 100: Understanding the Rails web model and scalability options

$ ruby em.rb 123

Page 101: Understanding the Rails web model and scalability options

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 4end

Page 102: Understanding the Rails web model and scalability options

$ ruby em.rb 4231

Page 103: Understanding the Rails web model and scalability options
Page 104: Understanding the Rails web model and scalability options

var http = require('http');

http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World');}).listen(9876);

Page 105: Understanding the Rails web model and scalability options

ab -n 1000 -c 5 http://127.0.0.1:9876/This is ApacheBench, Version 2.3 <$Revision: 1178079 $>...Concurrency Level: 5Time 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...

Page 106: Understanding the Rails web model and scalability options

require 'rubygems'require 'rack'

Rack::Handler::Thin.run Proc.new { [200, {"Content-Type" => "text/plain"}, ["Hello World!"]]}

Page 107: Understanding the Rails web model and scalability options

ab -n 1000 -c 5 http://127.0.0.1:8080/This is ApacheBench, Version 2.3 <$Revision: 1178079 $>...Concurrency Level: 5Time 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...

Page 108: Understanding the Rails web model and scalability options
Page 109: Understanding the Rails web model and scalability options

Node.js Ruby

libev Eventmachine, Cool.io

Google V8 MRI, JRuby, Rubinius

Less Resources, Faster Processing

More Resources, Slightly slower processing

callbacks only Threads, Fibers, Callbacks

Page 110: Understanding the Rails web model and scalability options

Node.js Ruby

libev Eventmachine, Cool.io

Google V8 MRI, JRuby, Rubinius

Less Resources, Faster Processing

More Resources, Slightly slower processing

callbacks only Threads, Fibers, Callbacks

Page 111: Understanding the Rails web model and scalability options

Node.js Ruby

libev Eventmachine, Cool.io

Google V8 MRI, JRuby, Rubinius

Less Resources, Faster Processing

More Resources, Slightly slower processing

callbacks only Threads, Fibers, Callbacks

Page 112: Understanding the Rails web model and scalability options

Node.js Ruby

libev Eventmachine, Cool.io

Google V8 MRI, JRuby, Rubinius

Less Resources, Faster Processing

More Resources, Slightly slower processing

callbacks only Threads, Fibers, Callbacks

Page 113: Understanding the Rails web model and scalability options

Node.js Ruby

libev Eventmachine, Cool.io

Google V8 MRI, JRuby, Rubinius

Less Resources, Faster Processing

More Resources, Slightly slower processing

callbacks only Threads, Fibers, Callbacks

Page 114: Understanding the Rails web model and scalability options

EM-Websocket

Page 115: Understanding the Rails web model and scalability options

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

Page 116: Understanding the Rails web model and scalability options

Caveats in Callback Driven Development

Page 117: Understanding the Rails web model and scalability options

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));});

Page 118: Understanding the Rails web model and scalability options

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)); });});

Page 119: Understanding the Rails web model and scalability options

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 endend

Page 120: Understanding the Rails web model and scalability options

“Callback Spaghetti”

Page 121: Understanding the Rails web model and scalability options

Ruby 1.9 Fibersto the rescue!

Page 122: Understanding the Rails web model and scalability options

number_generator = Fiber.new do start = 0 loop do start += 1 Fiber.yield(start) endend

Page 123: Understanding the Rails web model and scalability options

number_generator = Fiber.new do start = 0 loop do start += 1 Fiber.yield(start) endend

> number_generator.resume => 1

Page 124: Understanding the Rails web model and scalability options

number_generator = Fiber.new do start = 0 loop do start += 1 Fiber.yield(start) endend

> number_generator.resume => 1 > number_generator.resume => 2

Page 125: Understanding the Rails web model and scalability options

number_generator = Fiber.new do start = 0 loop do start += 1 Fiber.yield(start) endend

> number_generator.resume => 1 > number_generator.resume => 2 > number_generator.resume => 3

Page 126: Understanding the Rails web model and scalability options
Page 127: Understanding the Rails web model and scalability options

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

Page 128: Understanding the Rails web model and scalability options

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

Page 129: Understanding the Rails web model and scalability options

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

Page 130: Understanding the Rails web model and scalability options

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

Page 131: Understanding the Rails web model and scalability options

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

Page 132: Understanding the Rails web model and scalability options

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 endend

Page 133: Understanding the Rails web model and scalability options

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

Page 134: Understanding the Rails web model and scalability options

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.yieldend

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.resumeend

Page 135: Understanding the Rails web model and scalability options

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.yieldend

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.resumeend

Page 136: Understanding the Rails web model and scalability options

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.yieldend

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.resumeend

Page 137: Understanding the Rails web model and scalability options

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.yieldend

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.resumeend

Page 138: Understanding the Rails web model and scalability options

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.yieldend

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.resumeend

Page 139: Understanding the Rails web model and scalability options

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.yieldend

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.resumeend

Page 140: Understanding the Rails web model and scalability options

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.yieldend

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.resumeend

Page 141: Understanding the Rails web model and scalability options

EM-Synchrony

Page 142: Understanding the Rails web model and scalability options

EM.synchrony do page = EM::HttpRequest.new("http://www.google.com").get puts "Look Ma! No callbacks! Fetched page: #{page}" EM.stopend

# old wayEM.run do page = EM::HttpRequest.new("http://www.google.com").get page.callback do puts "Lame ... Fetched page: #{page}" EM.stop endend

Page 143: Understanding the Rails web model and scalability options

Goliath

Page 144: Understanding the Rails web model and scalability options

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] endend

Page 145: Understanding the Rails web model and scalability options

$ ruby echo.rb -p 9001

Page 146: Understanding the Rails web model and scalability options

$ ruby echo.rb -p 9001

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

Page 147: Understanding the Rails web model and scalability options

$ ruby echo.rb -p 9001

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

$ curl http://localhost:9001?echo=Hello%20World{"response":"Hello World"}

Page 148: Understanding the Rails web model and scalability options
Page 149: Understanding the Rails web model and scalability options

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

Page 150: Understanding the Rails web model and scalability options

Recap so far ...

Page 151: Understanding the Rails web model and scalability options
Page 152: Understanding the Rails web model and scalability options

Ruby can using Reactors to massively scale

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

One single Ruby process can handle thousands ofconcurrent requests

Web browsers got smarter with Websockets

Ruby implements Websocket support

Page 153: Understanding the Rails web model and scalability options

Pusher

Page 154: Understanding the Rails web model and scalability options

Rails App

Browser

Resque Queues

Persistentconnection!

async

Eventmachine App

sync

Page 155: Understanding the Rails web model and scalability options

Rails App

Browser

Resque Queues

Persistentconnection!

async

Eventmachine App

sync

Page 156: Understanding the Rails web model and scalability options

<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>

Page 157: Understanding the Rails web model and scalability options

<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>

Page 158: Understanding the Rails web model and scalability options

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

Page 159: Understanding the Rails web model and scalability options

time ruby pusher_sync.rb

real 0m14.585suser 0m0.583ssys 0m0.105s

Page 160: Understanding the Rails web model and scalability options

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 endend

Page 161: Understanding the Rails web model and scalability options

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 endend

Page 162: Understanding the Rails web model and scalability options

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 endend

Page 163: Understanding the Rails web model and scalability options

time ruby pusher_async.rb

real 0m1.129suser 0m0.649ssys 0m0.063s

Page 164: Understanding the Rails web model and scalability options

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.")});

Page 165: Understanding the Rails web model and scalability options
Page 166: Understanding the Rails web model and scalability options

Private Channels

Encryption

Authentication

Presence Events

Page 167: Understanding the Rails web model and scalability options
Page 168: Understanding the Rails web model and scalability options

Total API requests (11/02/2011)

(day has 86.400 seconds)

Page 169: Understanding the Rails web model and scalability options

13.969.264Total API requests (11/02/2011)

(day has 86.400 seconds)

Page 170: Understanding the Rails web model and scalability options

Amount of messages sentto clients since launch (11/02/2011)

Page 171: Understanding the Rails web model and scalability options

35.552.810.379Amount of messages sent

to clients since launch (11/02/2011)

Page 172: Understanding the Rails web model and scalability options

average latency (excluding internet - 11/02/2011)

Page 173: Understanding the Rails web model and scalability options

< 10msaverage latency (excluding internet - 11/02/2011)

Page 174: Understanding the Rails web model and scalability options

Wrapping up ...

Page 175: Understanding the Rails web model and scalability options
Page 176: Understanding the Rails web model and scalability options

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!

Page 177: Understanding the Rails web model and scalability options

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!

Page 178: Understanding the Rails web model and scalability options

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!

Page 179: Understanding the Rails web model and scalability options

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!

Page 180: Understanding the Rails web model and scalability options

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!

Page 181: Understanding the Rails web model and scalability options

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!

Page 182: Understanding the Rails web model and scalability options

Ilya Grigorik(igvita)

Page 183: Understanding the Rails web model and scalability options
Page 184: Understanding the Rails web model and scalability options

PostRank (acquired by Google!)

EM-Synchrony, Goliath

Google SPDY research

Page 185: Understanding the Rails web model and scalability options

Tony Arcieri(bascule)

Page 186: Understanding the Rails web model and scalability options
Page 187: Understanding the Rails web model and scalability options

Rev (later Cool.io), Revactor

Reia(Ruby syntax over Erlang, replaced by Elixir)

Celluloid (Threads abstraction to Actors)(Mark Perham used to create Sidekiq)

Page 188: Understanding the Rails web model and scalability options

Ruby is very flexible

Page 189: Understanding the Rails web model and scalability options

one more thing ...

Page 190: Understanding the Rails web model and scalability options

Passenger, Unicorn

NginX, HAProxy

Browser Browser Browser Browser Browser Browser

Page 191: Understanding the Rails web model and scalability options

JRuby - TorqueBox, Trinidad(multiple concurrent native threads)

NginX, HAProxy

Browser Browser Browser Browser Browser Browser

Page 192: Understanding the Rails web model and scalability options
Page 193: Understanding the Rails web model and scalability options

Ruby 1.9.xNative threads

(extensions can release the GIL)

JRubyNative threads

(no GIL)

RubiniusNative threads

(no GILcheck out the Puma webserver)

Page 194: Understanding the Rails web model and scalability options

Ruby 1.9.xNative threads

(extensions can release the GIL)

JRubyNative threads

(no GIL)

RubiniusNative threads

(no GILcheck out the Puma webserver)

Page 195: Understanding the Rails web model and scalability options

Ruby 1.9.xNative threads

(extensions can release the GIL)

JRubyNative threads

(no GIL)

RubiniusNative threads

(no GILcheck out the Puma webserver)

Page 196: Understanding the Rails web model and scalability options
Page 197: Understanding the Rails web model and scalability options
Page 198: Understanding the Rails web model and scalability options
Page 199: Understanding the Rails web model and scalability options

www.codeminer.com.brwww.akitaonrails.com@akitaonrails

Большое спасибо