SlideShare ist ein Scribd-Unternehmen logo
1 von 51
Downloaden Sie, um offline zu lesen
Scaling :ruby 
with Evented I/O 
Omer Gazit 
[github.com/omerisimo]
Scaling Strategies[] 
<< "Machines" 
<< "Processes" 
<< "Threads" 
<< "Reactor pattern"
Blocking I/O 
start 
wait for I/O [e.g. file,network] 
complete
Non-Blocking I/O 
start 
call I/O operation 
Do something else 
complete 
Kernel 
I/O 
callback()
:sync 
def sync_io(file_name) 
file = File.open(file_name) 
puts "File #{file_name} opened" 
end
:async 
def async_io(file_name) 
file = File.async_open(file_name) 
file.callback do |result| 
puts "File #{file_name} opened" 
end 
end
Reactor pattern 
“The reactor design pattern is an event 
handling pattern for handling service 
requests delivered concurrently… 
The service handler then demultiplexes the 
incoming requests and dispatches them 
synchronously to the associated request 
handlers.” 
-wikipedia
Reactor pattern 
“The reactor design pattern is an event 
handling pattern for handling service 
requests delivered concurrently… 
The service handler then demultiplexes the 
incoming requests and dispatches them 
synchronously to the associated request 
handlers.” 
-wikipedia
Reactor pattern 
IO Stream 
Demultiplexer 
Event Handler A 
Event Handler B 
Event Handler C 
Event 
Dispatcher
Reactor pattern 
A reactor is a single thread 
running an endless loop that 
reacts to incoming events
Reactor pattern 
A reactor is a single thread 
running an endless loop that 
reacts to incoming events
event_loop do 
while reactor_running? 
expired_timers.each { |timer| timer.process } 
new_network_io.each { |io| io.process } 
end
Reactor.when? 
● Proxies 
● Real time data delivery 
(Websockets) 
● Streaming 
● Background processing (MQ listener) 
● High throughput and mostly I/O 
bound
{ 
javascript: "Node.js", 
ruby: "EventMachine", 
perl: "AnyEvent", 
python: "Twisted", 
c: ["libev", "libevent"] 
} 
implementations=
EventMachine 
A toolkit for writing evented applications 
in Ruby
But node.js is so 
much faster... 
Is it really faster?
Simple HTTP Server 
Node.js 
var http = require('http'); 
http.createServer(function (request, response) { 
response.writeHead(200, 
{'Content-Type': 'text/plain'} 
); 
response.send('Hello Worldn'); 
}).listen(8080, '0.0.0.0'); 
console.log('Server running on port 8080');
Simple HTTP Server 
EventMachine 
EM.run do 
EM.start_server "0.0.0.0", 8080 do |server| 
def server.receive_data(data) 
response = EM::DelegatedHttpResponse .new(self) 
response.status = 200; 
response.content_type 'text/plain' 
response.content = "Hello World n" 
response.send_response 
end 
end 
end
Showdown 
results = { 
node: { req_per_sec: 2898, 
req_time_ms: 35 }, 
em: { req_per_sec: 6751, 
req_time_ms: 15 } 
} 
ab -n 1000 -c 100 "http://localhost:8080/" 
* executed on my MacBook Air
RabbitMQ Processor 
Node.js 
var amqp = require('amqp'); 
var connection = amqp.createConnection(); 
connection.on( 'ready', function() { 
connection.queue( 'my_queue' , function(queue) { 
queue.subscribe( function(payload) { 
console.log("Received message: " + payload.body); 
} 
}); 
var exchange = connection.exchange(); 
exchange.publish( 'my_queue' , { body: 'Hello World!' }); 
});
RabbitMQ Processor 
EventMachine 
require 'amqp' 
EM.run do 
connection = AMQP.connect(host: '0.0.0.0') 
channel = AMQP::Channel .new(connection) 
queue = channel.queue( "my_queue" ) 
queue.subscribe do |metadata, payload| 
puts "Received message: #{payload}." 
end 
exchange = channel.default_exchange 
exchange.publish "Hello world!" ,routing_key : "my_queue" 
end
Showdown 
average_time_ms = { 
node: 4285, 
em: 3488 
} 
send and receive 10k messages 
* executed on my MacBook Air
EM can be really fast 
If used correctly!
Never Block the 
Event Loop
Never Block 
Blocking Non-Blocking 
EM.run do 
puts "Started EM" 
sleep 2.0 
puts "Shutting down EM" 
EM.stop 
end 
EM.run do 
puts "Started EM" 
EM.add_periodic_timer( 1.0) do 
puts "Tick" 
end 
EM.add_timer( 2.0) do 
puts "Shutting down EM" 
EM.stop 
end 
end
Never Block 
Blocking Non-Blocking 
require 'net/http' 
EM.run do 
response = Net::HTTP.get(URL) 
puts "Completed HTTP request" 
EM.stop 
end 
require 'em-http' 
EM.run do 
http = EM::HttpRequest .new(URL).get 
http.callback do |response| 
puts "Completed HTTP request" 
EM.stop 
end 
end
module NonBlock 
<< "igrigorik/em-http-request" # Asynchronous HTTP Client 
<< "eventmachine/evma_httpserver" # HTTP Server 
<< "igrigorik/em-websocket" # WebSockets server 
<< "igrigorik/em-proxy" # High-performance transparent proxies 
<< "brianmario/mysql2" # Make sure to use with :async => true 
<< "royaltm/ruby-em-pg-client" # PostgreSQL EM client 
<< "bcg/em-mongo" # EM MongoDB driver (based off of RMongo) 
<< "simulacre/em-ssh" # EM compatible Net::SSH 
<< "pressly/uber-s3" # S3 client with asynchronous I/O adapters 
<< "tmm1/amqp" # AMQP client for EM 
* See full list of protocols at: github.com/eventmachine/eventmachine/wiki/Protocol-Implementations
module NonBlock 
<< "igrigorik/em-http-request" 
<< "eventmachine/evma_httpserver" 
<< "igrigorik/em-websocket" 
<< "igrigorik/em-proxy" 
<< "brianmario/mysql2" 
<< "royaltm/ruby-em-pg-client" 
<< "bcg/em-mongo" 
<< "simulacre/em-ssh" 
<< "pressly/uber-s3" 
<< "tmm1/amqp" 
* See full list of protocols at: github.com/eventmachine/eventmachine/wiki/Protocol-Implementations
Never Block the 
Event Loop
EM.defer 
Defer blocking code to a thread 
EM.run do 
long_operation = proc { 
sleep(1.0) 
"result" 
} 
callback = proc {|result| 
puts "Received #{result}" 
EM.stop 
} 
EM.defer(long_operation, callback) 
end
EM.next_tick 
Postpone execution to the next iteration 
Blocking Non-Blocking 
EM.run do 
(1..10000).each do |index| 
puts "Processing #{index}" 
end 
EM.stop 
end 
EM.run do 
index = 0 
process_index = proc { 
if index < 10000 
puts "Processing #{index}" 
index += 1 
EM.next_tick &process_index 
else 
EM.stop 
end 
} 
EM.next_tick &process_index 
end
EM::Primitives
EM::Deferrable 
EM::Deferrable != EM.defer 
class DeferrableTimer 
include EM::Deferrable 
def wait 
EM.add_timer( 1.0) do 
succeed "result" 
end 
self 
end 
end 
EM.run do 
timer = DeferrableTimer .new.wait 
timer.callback do |result| 
puts "1 second has passed!" 
EM.stop 
end 
end
EM::Connection 
class EchoServer < EM::Connection 
def post_init 
puts "Client connecting" 
end 
def receive_data (data) 
puts "Client sending data #{data}" 
send_data ">> #{data}" 
end 
def unbind 
puts "Client disconnecting" 
end 
end 
EM.run do 
EM.start_server( "0.0.0.0", 9000, EchoServer ) # Listen on TCP socket 
end
EM::Queue 
A cross thread, reactor scheduled, linear queue 
EM.run do 
queue = EM::Queue.new 
queue_handler = proc { |message| 
puts "Handling message #{message}" 
EM.next_tick{ queue.pop( &queue_handler) } 
} 
EM.next_tick{ queue.pop( &queue_handler) } 
EM.add_periodic_timer( 1.0) do 
message = Time.now.to_s 
puts "Pushing message ' #{message}' to queue" 
queue.push(message) 
end 
end
EM::Channel 
Provides a simple thread-safe way to transfer data 
between (typically)long running tasks 
EM.run do 
channel = EM::Channel.new 
handler_1 = proc { | message| puts "Handler 1 message #{message}" } 
handler_2 = proc { | message| puts "Handler 2 message #{message}" } 
channel.subscribe &handler_1 
channel.subscribe &handler_2 
EM.add_periodic_timer( 1.0) do 
message = Time.now.to_s 
puts "Sending message ' #{message}' to channel" 
channel << message 
end 
end
EM::Primitives 
<< EM::Queue # A cross thread, reactor scheduled, 
linear queue 
<< EM::Channel # Simple thread-safe way to transfer 
data between (typically)long running tasks 
<< EM::Iterator # A simple iterator for concurrent 
asynchronous work 
<< EM.System() # Run external commands without 
blocking
EM.run do 
EM.add_timer( 1) do 
json = nil 
begin 
data = JSON.parse(json) 
puts "Parsed Json data: #{data}" 
rescue StandardException => e 
puts "Error: #{e.message}" 
end 
EM.stop 
end 
end 
Error Handling
Error Handling 
EM.run do 
EM.add_timer( 1) do 
http = EM::HttpRequest .new(BAD_URI).get 
http.callback do 
puts "Completed HTTP request" 
EM.stop 
end 
http.errback do |error| 
puts "Error: #{error.error }" 
EM.stop 
end 
end 
end
EM::Synchrony 
Fiber aware EventMachine clients and 
convenience classes 
github.com/igrigorik/em-synchrony
EM::Synchrony 
em-synchrony/em-http 
require 'em-synchrony' 
require 'em-synchrony/em-http' 
EM.synchrony do 
res = EM::HttpRequest .new(URL).get 
puts "Response: #{res.response }" 
EM.stop 
end 
em-http-request 
require 'eventmachine' 
require 'em-http' 
EM.run do 
http = EM::HttpRequest .new(URL).get 
http.callback do 
puts "Completed HTTP request" 
EM.stop 
end 
end
Testing
EM::Spec 
require 'em-spec/rspec' 
describe LazyCalculator do 
include EM::SpecHelper 
default_timeout( 2.0) 
it "divides x by y" do 
em do 
calc = LazyCalculator .new.divide(6,3) 
calc.callback do |result| 
expect(result).to eq 2 
done 
end 
end 
end 
end 
class LazyCalculator 
include EM::Deferrable 
def divide(x, y) 
EM.add_timer( 1.0) do 
if(y == 0) 
fail ZeroDivisionError .new 
else 
result = x/y 
succeed result 
end 
end 
self 
end 
end
EM::Spec 
require 'em-spec/rspec' 
describe LazyCalculator do 
include EM::SpecHelper 
default_timeout( 2.0) 
it "fails when dividing by zero" do 
em do 
calc = LazyCalculator .new.divide(6,0) 
calc.errback do |error| 
expect(error).to be_a ZeroDivisionError 
done 
end 
end 
end 
end 
class LazyCalculator 
include EM::Deferrable 
def divide(x, y) 
EM.add_timer( 1.0) do 
if(y == 0) 
fail ZeroDivisionError .new 
else 
result = x/y 
succeed result 
end 
end 
self 
end 
end
RSpec::EM::FakeClock 
require 'rspec/em' 
describe LazyCalculator do 
include RSpec::EM::FakeClock 
before { clock.stub } 
after { clock.reset } 
it "divides x by y" do 
calc = LazyCalculator .new.divide(6,3) 
expect(calc).to receive(: succeed).with 2 
clock.tick( 1) 
end 
it "fails when dividing by zero" do 
calc = LazyCalculator .new.divide(6,0) 
expect(calc).to receive(: fail).with(kind_of( ZeroDivisionError )) 
clock.tick( 1) 
end 
end
Project Demo 
A proxy for Google Geocode API
Limitations 
● Can only use async libraries or 
have to defer to threads. 
● Hard to debug (no stack trace) 
● Harder to test 
● Difficult to build full blown 
websites.
Caveats 
● Low community support 
● The last release is almost two 
years old
Summary 
● Evented I/O offers a cost effective 
way to scale applications 
● EventMachine is a fast, scalable 
and production ready toolbox 
● Write elegant event-driven code 
● It is not the right tool for every 
problem
EM.next? 
<< ['em_synchrony' + Fiber] 
<< ['async_sinatra' + Thin] # Sinatra on EM 
<< ['goliath'] # Non-blocking web framework 
<< [EM.epoll + EM.kqueue] # maximize 
demultiplexer polling limits 
<< [Celluloid + Celluloid.IO] # Actor 
pattern + Evented I/O
EM.stop 
Thank you 
Code examples: github.com/omerisimo/em_underground

Weitere ähnliche Inhalte

Was ist angesagt?

Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.comRuby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.comIlya Grigorik
 
0-60 with Goliath: High performance web services
0-60 with Goliath: High performance web services0-60 with Goliath: High performance web services
0-60 with Goliath: High performance web servicesIlya Grigorik
 
Concurrency in Python
Concurrency in PythonConcurrency in Python
Concurrency in PythonMosky Liu
 
Why async matters
Why async mattersWhy async matters
Why async matterstimbc
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxbobmcwhirter
 
Ruby Proxies for Scale, Performance, and Monitoring
Ruby Proxies for Scale, Performance, and MonitoringRuby Proxies for Scale, Performance, and Monitoring
Ruby Proxies for Scale, Performance, and MonitoringIlya Grigorik
 
WebSockets wiith Scala and Play! Framework
WebSockets wiith Scala and Play! FrameworkWebSockets wiith Scala and Play! Framework
WebSockets wiith Scala and Play! FrameworkFabio Tiriticco
 
Node.js - Advanced Basics
Node.js - Advanced BasicsNode.js - Advanced Basics
Node.js - Advanced BasicsDoug Jones
 
Streams are Awesome - (Node.js) TimesOpen Sep 2012
Streams are Awesome - (Node.js) TimesOpen Sep 2012 Streams are Awesome - (Node.js) TimesOpen Sep 2012
Streams are Awesome - (Node.js) TimesOpen Sep 2012 Tom Croucher
 
A complete guide to Node.js
A complete guide to Node.jsA complete guide to Node.js
A complete guide to Node.jsPrabin Silwal
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...bobmcwhirter
 
Introduction to Python Celery
Introduction to Python CeleryIntroduction to Python Celery
Introduction to Python CeleryMahendra M
 
Async programming and python
Async programming and pythonAsync programming and python
Async programming and pythonChetan Giridhar
 
TorqueBox for Rubyists
TorqueBox for RubyistsTorqueBox for Rubyists
TorqueBox for Rubyistsbobmcwhirter
 
Nodejs Explained with Examples
Nodejs Explained with ExamplesNodejs Explained with Examples
Nodejs Explained with ExamplesGabriele Lana
 
How NOT to write in Node.js
How NOT to write in Node.jsHow NOT to write in Node.js
How NOT to write in Node.jsPiotr Pelczar
 
Node.js: A Guided Tour
Node.js: A Guided TourNode.js: A Guided Tour
Node.js: A Guided Tourcacois
 
Introduction to node.js
Introduction to node.jsIntroduction to node.js
Introduction to node.jsjacekbecela
 

Was ist angesagt? (20)

Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.comRuby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
 
0-60 with Goliath: High performance web services
0-60 with Goliath: High performance web services0-60 with Goliath: High performance web services
0-60 with Goliath: High performance web services
 
Concurrency in Python
Concurrency in PythonConcurrency in Python
Concurrency in Python
 
Why async matters
Why async mattersWhy async matters
Why async matters
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBox
 
Ruby Proxies for Scale, Performance, and Monitoring
Ruby Proxies for Scale, Performance, and MonitoringRuby Proxies for Scale, Performance, and Monitoring
Ruby Proxies for Scale, Performance, and Monitoring
 
WebSockets wiith Scala and Play! Framework
WebSockets wiith Scala and Play! FrameworkWebSockets wiith Scala and Play! Framework
WebSockets wiith Scala and Play! Framework
 
About Node.js
About Node.jsAbout Node.js
About Node.js
 
Node.js - Advanced Basics
Node.js - Advanced BasicsNode.js - Advanced Basics
Node.js - Advanced Basics
 
Streams are Awesome - (Node.js) TimesOpen Sep 2012
Streams are Awesome - (Node.js) TimesOpen Sep 2012 Streams are Awesome - (Node.js) TimesOpen Sep 2012
Streams are Awesome - (Node.js) TimesOpen Sep 2012
 
A complete guide to Node.js
A complete guide to Node.jsA complete guide to Node.js
A complete guide to Node.js
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
 
Devignition 2011
Devignition 2011Devignition 2011
Devignition 2011
 
Introduction to Python Celery
Introduction to Python CeleryIntroduction to Python Celery
Introduction to Python Celery
 
Async programming and python
Async programming and pythonAsync programming and python
Async programming and python
 
TorqueBox for Rubyists
TorqueBox for RubyistsTorqueBox for Rubyists
TorqueBox for Rubyists
 
Nodejs Explained with Examples
Nodejs Explained with ExamplesNodejs Explained with Examples
Nodejs Explained with Examples
 
How NOT to write in Node.js
How NOT to write in Node.jsHow NOT to write in Node.js
How NOT to write in Node.js
 
Node.js: A Guided Tour
Node.js: A Guided TourNode.js: A Guided Tour
Node.js: A Guided Tour
 
Introduction to node.js
Introduction to node.jsIntroduction to node.js
Introduction to node.js
 

Ähnlich wie Scaling Ruby with Evented I/O - Ruby underground

A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...Tom Croucher
 
A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...Tom Croucher
 
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9Ilya Grigorik
 
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Masahiro Nagano
 
Ruby HTTP clients comparison
Ruby HTTP clients comparisonRuby HTTP clients comparison
Ruby HTTP clients comparisonHiroshi Nakamura
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applicationsTom Croucher
 
692015 programming assignment 1 building a multi­threaded w
692015 programming assignment 1 building a multi­threaded w692015 programming assignment 1 building a multi­threaded w
692015 programming assignment 1 building a multi­threaded wsmile790243
 
[Type text]ECET465Project 2Project Assignment 2 Building a Mul.docx
[Type text]ECET465Project 2Project Assignment 2 Building a Mul.docx[Type text]ECET465Project 2Project Assignment 2 Building a Mul.docx
[Type text]ECET465Project 2Project Assignment 2 Building a Mul.docxhanneloremccaffery
 
8 Minutes On Rack
8 Minutes On Rack8 Minutes On Rack
8 Minutes On Rackdanwrong
 
Project Assignment 2 Building a Multi-Threaded Web ServerThis pro.docx
Project Assignment 2 Building a Multi-Threaded Web ServerThis pro.docxProject Assignment 2 Building a Multi-Threaded Web ServerThis pro.docx
Project Assignment 2 Building a Multi-Threaded Web ServerThis pro.docxkacie8xcheco
 
Live Streaming & Server Sent Events
Live Streaming & Server Sent EventsLive Streaming & Server Sent Events
Live Streaming & Server Sent Eventstkramar
 
Future Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETFuture Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETGianluca Carucci
 
1)Building a MultiThreaded Web ServerIn this lab we will devel
1)Building a MultiThreaded Web ServerIn this lab we will devel1)Building a MultiThreaded Web ServerIn this lab we will devel
1)Building a MultiThreaded Web ServerIn this lab we will develAgripinaBeaulieuyw
 

Ähnlich wie Scaling Ruby with Evented I/O - Ruby underground (20)

A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...
 
A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...A language for the Internet: Why JavaScript and Node.js is right for Internet...
A language for the Internet: Why JavaScript and Node.js is right for Internet...
 
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
 
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015
 
Node.js
Node.jsNode.js
Node.js
 
Ruby HTTP clients comparison
Ruby HTTP clients comparisonRuby HTTP clients comparison
Ruby HTTP clients comparison
 
Intro to Node
Intro to NodeIntro to Node
Intro to Node
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
Rack
RackRack
Rack
 
692015 programming assignment 1 building a multi­threaded w
692015 programming assignment 1 building a multi­threaded w692015 programming assignment 1 building a multi­threaded w
692015 programming assignment 1 building a multi­threaded w
 
[Type text]ECET465Project 2Project Assignment 2 Building a Mul.docx
[Type text]ECET465Project 2Project Assignment 2 Building a Mul.docx[Type text]ECET465Project 2Project Assignment 2 Building a Mul.docx
[Type text]ECET465Project 2Project Assignment 2 Building a Mul.docx
 
8 Minutes On Rack
8 Minutes On Rack8 Minutes On Rack
8 Minutes On Rack
 
Project Assignment 2 Building a Multi-Threaded Web ServerThis pro.docx
Project Assignment 2 Building a Multi-Threaded Web ServerThis pro.docxProject Assignment 2 Building a Multi-Threaded Web ServerThis pro.docx
Project Assignment 2 Building a Multi-Threaded Web ServerThis pro.docx
 
Live Streaming & Server Sent Events
Live Streaming & Server Sent EventsLive Streaming & Server Sent Events
Live Streaming & Server Sent Events
 
Future Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETFuture Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NET
 
Server Side Swift: Vapor
Server Side Swift: VaporServer Side Swift: Vapor
Server Side Swift: Vapor
 
Test driven infrastructure
Test driven infrastructureTest driven infrastructure
Test driven infrastructure
 
Web
WebWeb
Web
 
1)Building a MultiThreaded Web ServerIn this lab we will devel
1)Building a MultiThreaded Web ServerIn this lab we will devel1)Building a MultiThreaded Web ServerIn this lab we will devel
1)Building a MultiThreaded Web ServerIn this lab we will devel
 
Web Server.pdf
Web Server.pdfWeb Server.pdf
Web Server.pdf
 

Kürzlich hochgeladen

(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendArshad QA
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....ShaimaaMohamedGalal
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 

Kürzlich hochgeladen (20)

(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and Backend
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 

Scaling Ruby with Evented I/O - Ruby underground

  • 1. Scaling :ruby with Evented I/O Omer Gazit [github.com/omerisimo]
  • 2. Scaling Strategies[] << "Machines" << "Processes" << "Threads" << "Reactor pattern"
  • 3. Blocking I/O start wait for I/O [e.g. file,network] complete
  • 4. Non-Blocking I/O start call I/O operation Do something else complete Kernel I/O callback()
  • 5. :sync def sync_io(file_name) file = File.open(file_name) puts "File #{file_name} opened" end
  • 6. :async def async_io(file_name) file = File.async_open(file_name) file.callback do |result| puts "File #{file_name} opened" end end
  • 7. Reactor pattern “The reactor design pattern is an event handling pattern for handling service requests delivered concurrently… The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers.” -wikipedia
  • 8. Reactor pattern “The reactor design pattern is an event handling pattern for handling service requests delivered concurrently… The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers.” -wikipedia
  • 9. Reactor pattern IO Stream Demultiplexer Event Handler A Event Handler B Event Handler C Event Dispatcher
  • 10. Reactor pattern A reactor is a single thread running an endless loop that reacts to incoming events
  • 11. Reactor pattern A reactor is a single thread running an endless loop that reacts to incoming events
  • 12. event_loop do while reactor_running? expired_timers.each { |timer| timer.process } new_network_io.each { |io| io.process } end
  • 13. Reactor.when? ● Proxies ● Real time data delivery (Websockets) ● Streaming ● Background processing (MQ listener) ● High throughput and mostly I/O bound
  • 14. { javascript: "Node.js", ruby: "EventMachine", perl: "AnyEvent", python: "Twisted", c: ["libev", "libevent"] } implementations=
  • 15. EventMachine A toolkit for writing evented applications in Ruby
  • 16. But node.js is so much faster... Is it really faster?
  • 17. Simple HTTP Server Node.js var http = require('http'); http.createServer(function (request, response) { response.writeHead(200, {'Content-Type': 'text/plain'} ); response.send('Hello Worldn'); }).listen(8080, '0.0.0.0'); console.log('Server running on port 8080');
  • 18. Simple HTTP Server EventMachine EM.run do EM.start_server "0.0.0.0", 8080 do |server| def server.receive_data(data) response = EM::DelegatedHttpResponse .new(self) response.status = 200; response.content_type 'text/plain' response.content = "Hello World n" response.send_response end end end
  • 19. Showdown results = { node: { req_per_sec: 2898, req_time_ms: 35 }, em: { req_per_sec: 6751, req_time_ms: 15 } } ab -n 1000 -c 100 "http://localhost:8080/" * executed on my MacBook Air
  • 20. RabbitMQ Processor Node.js var amqp = require('amqp'); var connection = amqp.createConnection(); connection.on( 'ready', function() { connection.queue( 'my_queue' , function(queue) { queue.subscribe( function(payload) { console.log("Received message: " + payload.body); } }); var exchange = connection.exchange(); exchange.publish( 'my_queue' , { body: 'Hello World!' }); });
  • 21. RabbitMQ Processor EventMachine require 'amqp' EM.run do connection = AMQP.connect(host: '0.0.0.0') channel = AMQP::Channel .new(connection) queue = channel.queue( "my_queue" ) queue.subscribe do |metadata, payload| puts "Received message: #{payload}." end exchange = channel.default_exchange exchange.publish "Hello world!" ,routing_key : "my_queue" end
  • 22. Showdown average_time_ms = { node: 4285, em: 3488 } send and receive 10k messages * executed on my MacBook Air
  • 23. EM can be really fast If used correctly!
  • 24. Never Block the Event Loop
  • 25. Never Block Blocking Non-Blocking EM.run do puts "Started EM" sleep 2.0 puts "Shutting down EM" EM.stop end EM.run do puts "Started EM" EM.add_periodic_timer( 1.0) do puts "Tick" end EM.add_timer( 2.0) do puts "Shutting down EM" EM.stop end end
  • 26. Never Block Blocking Non-Blocking require 'net/http' EM.run do response = Net::HTTP.get(URL) puts "Completed HTTP request" EM.stop end require 'em-http' EM.run do http = EM::HttpRequest .new(URL).get http.callback do |response| puts "Completed HTTP request" EM.stop end end
  • 27. module NonBlock << "igrigorik/em-http-request" # Asynchronous HTTP Client << "eventmachine/evma_httpserver" # HTTP Server << "igrigorik/em-websocket" # WebSockets server << "igrigorik/em-proxy" # High-performance transparent proxies << "brianmario/mysql2" # Make sure to use with :async => true << "royaltm/ruby-em-pg-client" # PostgreSQL EM client << "bcg/em-mongo" # EM MongoDB driver (based off of RMongo) << "simulacre/em-ssh" # EM compatible Net::SSH << "pressly/uber-s3" # S3 client with asynchronous I/O adapters << "tmm1/amqp" # AMQP client for EM * See full list of protocols at: github.com/eventmachine/eventmachine/wiki/Protocol-Implementations
  • 28. module NonBlock << "igrigorik/em-http-request" << "eventmachine/evma_httpserver" << "igrigorik/em-websocket" << "igrigorik/em-proxy" << "brianmario/mysql2" << "royaltm/ruby-em-pg-client" << "bcg/em-mongo" << "simulacre/em-ssh" << "pressly/uber-s3" << "tmm1/amqp" * See full list of protocols at: github.com/eventmachine/eventmachine/wiki/Protocol-Implementations
  • 29. Never Block the Event Loop
  • 30. EM.defer Defer blocking code to a thread EM.run do long_operation = proc { sleep(1.0) "result" } callback = proc {|result| puts "Received #{result}" EM.stop } EM.defer(long_operation, callback) end
  • 31. EM.next_tick Postpone execution to the next iteration Blocking Non-Blocking EM.run do (1..10000).each do |index| puts "Processing #{index}" end EM.stop end EM.run do index = 0 process_index = proc { if index < 10000 puts "Processing #{index}" index += 1 EM.next_tick &process_index else EM.stop end } EM.next_tick &process_index end
  • 33. EM::Deferrable EM::Deferrable != EM.defer class DeferrableTimer include EM::Deferrable def wait EM.add_timer( 1.0) do succeed "result" end self end end EM.run do timer = DeferrableTimer .new.wait timer.callback do |result| puts "1 second has passed!" EM.stop end end
  • 34. EM::Connection class EchoServer < EM::Connection def post_init puts "Client connecting" end def receive_data (data) puts "Client sending data #{data}" send_data ">> #{data}" end def unbind puts "Client disconnecting" end end EM.run do EM.start_server( "0.0.0.0", 9000, EchoServer ) # Listen on TCP socket end
  • 35. EM::Queue A cross thread, reactor scheduled, linear queue EM.run do queue = EM::Queue.new queue_handler = proc { |message| puts "Handling message #{message}" EM.next_tick{ queue.pop( &queue_handler) } } EM.next_tick{ queue.pop( &queue_handler) } EM.add_periodic_timer( 1.0) do message = Time.now.to_s puts "Pushing message ' #{message}' to queue" queue.push(message) end end
  • 36. EM::Channel Provides a simple thread-safe way to transfer data between (typically)long running tasks EM.run do channel = EM::Channel.new handler_1 = proc { | message| puts "Handler 1 message #{message}" } handler_2 = proc { | message| puts "Handler 2 message #{message}" } channel.subscribe &handler_1 channel.subscribe &handler_2 EM.add_periodic_timer( 1.0) do message = Time.now.to_s puts "Sending message ' #{message}' to channel" channel << message end end
  • 37. EM::Primitives << EM::Queue # A cross thread, reactor scheduled, linear queue << EM::Channel # Simple thread-safe way to transfer data between (typically)long running tasks << EM::Iterator # A simple iterator for concurrent asynchronous work << EM.System() # Run external commands without blocking
  • 38. EM.run do EM.add_timer( 1) do json = nil begin data = JSON.parse(json) puts "Parsed Json data: #{data}" rescue StandardException => e puts "Error: #{e.message}" end EM.stop end end Error Handling
  • 39. Error Handling EM.run do EM.add_timer( 1) do http = EM::HttpRequest .new(BAD_URI).get http.callback do puts "Completed HTTP request" EM.stop end http.errback do |error| puts "Error: #{error.error }" EM.stop end end end
  • 40. EM::Synchrony Fiber aware EventMachine clients and convenience classes github.com/igrigorik/em-synchrony
  • 41. EM::Synchrony em-synchrony/em-http require 'em-synchrony' require 'em-synchrony/em-http' EM.synchrony do res = EM::HttpRequest .new(URL).get puts "Response: #{res.response }" EM.stop end em-http-request require 'eventmachine' require 'em-http' EM.run do http = EM::HttpRequest .new(URL).get http.callback do puts "Completed HTTP request" EM.stop end end
  • 43. EM::Spec require 'em-spec/rspec' describe LazyCalculator do include EM::SpecHelper default_timeout( 2.0) it "divides x by y" do em do calc = LazyCalculator .new.divide(6,3) calc.callback do |result| expect(result).to eq 2 done end end end end class LazyCalculator include EM::Deferrable def divide(x, y) EM.add_timer( 1.0) do if(y == 0) fail ZeroDivisionError .new else result = x/y succeed result end end self end end
  • 44. EM::Spec require 'em-spec/rspec' describe LazyCalculator do include EM::SpecHelper default_timeout( 2.0) it "fails when dividing by zero" do em do calc = LazyCalculator .new.divide(6,0) calc.errback do |error| expect(error).to be_a ZeroDivisionError done end end end end class LazyCalculator include EM::Deferrable def divide(x, y) EM.add_timer( 1.0) do if(y == 0) fail ZeroDivisionError .new else result = x/y succeed result end end self end end
  • 45. RSpec::EM::FakeClock require 'rspec/em' describe LazyCalculator do include RSpec::EM::FakeClock before { clock.stub } after { clock.reset } it "divides x by y" do calc = LazyCalculator .new.divide(6,3) expect(calc).to receive(: succeed).with 2 clock.tick( 1) end it "fails when dividing by zero" do calc = LazyCalculator .new.divide(6,0) expect(calc).to receive(: fail).with(kind_of( ZeroDivisionError )) clock.tick( 1) end end
  • 46. Project Demo A proxy for Google Geocode API
  • 47. Limitations ● Can only use async libraries or have to defer to threads. ● Hard to debug (no stack trace) ● Harder to test ● Difficult to build full blown websites.
  • 48. Caveats ● Low community support ● The last release is almost two years old
  • 49. Summary ● Evented I/O offers a cost effective way to scale applications ● EventMachine is a fast, scalable and production ready toolbox ● Write elegant event-driven code ● It is not the right tool for every problem
  • 50. EM.next? << ['em_synchrony' + Fiber] << ['async_sinatra' + Thin] # Sinatra on EM << ['goliath'] # Non-blocking web framework << [EM.epoll + EM.kqueue] # maximize demultiplexer polling limits << [Celluloid + Celluloid.IO] # Actor pattern + Evented I/O
  • 51. EM.stop Thank you Code examples: github.com/omerisimo/em_underground

Hinweis der Redaktion

  1. Been around for over 10 years Widely used in production by many companies Postrank (purchased by Google) Github Heroku Engine Yard For example Thin web server is implemented using EventMachine
  2. Demo
  3. Show demo