SlideShare uma empresa Scribd logo
1 de 63
EventMachine
  EM.run{ awesome_stuff! }




                             Christopher Spring
@autonomous
EventMachine
EventMachine
• Mostly IO bound
• Handle thousands
  concurrent connections
• Stream data
• Real time data delivery
• You’ve got Mad Ruby Skills
What is EventMachine?

• Toolkit for creating evented applications
• Implementation of the Reactor Pattern
• MRI,YARV, jRuby, Rubinius
Evented?
Evented?
puts(1)
puts(2)
puts(3)
Evented?
puts(1)
puts(2)
puts(3)
             puts(1)
             work{ puts(3) }
             puts(2)
Reactor pattern
“Event handling pattern for handling service
requests delivered concurrently to a service
handler by one or more inputs. The service
handler then demultiplexes the incoming
requests and dispatches them synchronously
to the associated request handlers.”




                             http://en.wikipedia.org/wiki/Reactor_pattern
Http   Keyboard     Udp   etc




                   Service handler
                    Demultiplexer

                   Event dispatcher




Event Handler A
Event Handler B
Event Handler C
Event Handler D
Http   Keyboard     Udp   etc




                   Service handler
                    Demultiplexer

                   Event dispatcher




Event Handler A
Event Handler B
Event Handler C
Event Handler D
Http   Keyboard     Udp   etc




                   Service handler
                    Demultiplexer

                   Event dispatcher


                                            Thread 1

Event Handler A                             Thread 2
Event Handler B
                                               ...
Event Handler C
Event Handler D                             Thread 20
Benefits

• Application code separate from reactor
• Non blocking IO
• Single process
• No threads!
Limitations


• Demultiplexing limits
• Some others we’ll cover later...
Teh Basics
• EM.run
• EM.connection
• EM.next_tick
• EM.defer
• EM::Queue
• EM::Channel
Teh Basics
• EM.run
• EM.connection
• EM.next_tick
• EM.defer
• EM::Queue
• EM::Channel
require "rubygems"
require "eventmachine"

EM.run do
  # ...
  EM.stop
end
... don’t do this!

• big ass loops
  •   1_000_000.times{}

  •   while condition?

• sleep
• blocking IO
Teh Basics
• EM.run
• EM.connection
• EM.next_tick
• EM.defer
• EM::Queue
• EM::Channel
class EchoServer < EM::Connection
  def post_init
    puts "New connection"
  end

  def unbind
    puts "Connection closed"
  end

  def receive_data(data)
    send_data ">> #{data}"
  end
end

EM.run do
  EM.start_server('127.0.0.1', 9000, EchoServer)
  puts "Started server at 127.0.0.1:9000"
end
class EchoServer < EM::Connection
  def post_init
    puts "New connection"
  end

  def unbind
    puts "Connection closed"            #   $ telnet localhost 9000
  end                                   #   Hello
                                        #   >> Hello
  def receive_data(data)                #   Bye
    send_data ">> #{data}"              #   >> Bye
  end
end

EM.run do
  EM.start_server('127.0.0.1', 9000, EchoServer)
  puts "Started server at 127.0.0.1:9000"
end
# TCP
EM.run do
  EM.start_server('127.0.0.1', 9000, EchoServer)
end

# UDP
EM.run do
  EM.open_datagram_socket('127.0.0.1', 9000, EchoServer)
end

# Unix-domain server
EM.run do
  EM.start_unix_domain_server('/tmp/sock', nil, EchoServer)
end
class EchoClient < EM::Connection
  def post_init
    puts "Sending stuff to server"
    send_data("Why, hello there!")
  end

  def unbind
    puts "Connection closed"
  end

  def receive_data(data)
    puts ">> #{data}"
  end
end

EM.run do
  EM.connect('127.0.0.1', 9000, EchoClient)
end
class EchoClient < EM::Connection
  def post_init
    puts "Sending stuff to server"
    send_data("Why, hello there!")
  end

  def unbind
    puts "Connection closed"
  end

  def receive_data(data)
    puts ">> #{data}"
  end
end

EM.run do
  EM.connect('127.0.0.1', 9000, EchoClient)
end
Teh Basics
• EM.run
• EM.connection
• EM.next_tick
• EM.defer
• EM::Queue
• EM::Channel
EM.run do
  EM.next_tick do
    # ... awesome stuff
  end
end
Task 1

Task 2

Task 3
Task 1

Task 2

Task 3



 EM.run{ }
Task 1

Task 2

Task 3



 EM.run{ }



 EM.next_tick{ }
Teh Basics
• EM.run
• EM.connection
• EM.next_tick
• EM.defer
• EM::Queue
• EM::Channel
EM.run do
  EM.defer do
    send_email( user1 )
  end

  EM.defer do
    send_email( user2 )
  end

  EM.defer do
    send_email( user3 )
  end
end
Email 1

Email 2

Email 3
Email 1

Email 2

Email 3



 EM.defer{ }
EM.run do
  get_stuff = Proc.new do
    # ...
    long_running_io()
  end

  use_stuff = Proc.new do |io_results|
    # ...
  end

  # ...
  EM.defer( get_stuff, use_stuff )
end
Teh Basics
• EM.run
• EM.connection
• next_tick; add_timer; add_periodic_timer
• EM.defer
• EM::Queue
• EM::Channel
EM.run do
  queue = EM::Queue.new

  # ...
  queue.push( data1, data2 )

  # ...
  queue.pop { |data| puts data } # >> data1

end
EM.run do
  queue = EM::Queue.new

  EM.defer do
    sleep( 2 )
    queue.push( 'some@email.com' )
    sleep( 3 )
    queue.push( 'some@one.com')
  end

  welcomer = Proc.new do |email|
    send_welcome( email )
    EM.next_tick( queue.pop(&welcomer) )
  end

  queue.pop(&welcomer);
end
Teh Basics
• EM.run
• EM.connection
• EM.next_tick
• EM.defer
• EM::Queue
• EM::Channel
EM.run do
  channel = EM::Channel.new

  EM.defer do
    channel.subscribe do |msg|
      puts "Received #{msg}"
    end
  end

  EM.add_periodic_timer(1) do
    channel << Time.now
  end
end
Deferrable
• Light weight concurrency
• Delayed execution with triggers
 • :succeeded
 • :failed
 • nil
• callback and errback
class LoanRequest
  include EM::Deferrable

  def initialize( name )
    @name = name
    callback do |who|
      puts "Approved #{who}!"
    end

    errback do |who|
      puts "Denied #{who}!"
    end
  end

  def approved!
    # succeed( *args )
    set_deferred_status(:succeeded, @name)
  end

  def denied!
    # fail( *args )
    set_deferred_status(:failed, @name)
  end
end
class LoanRequest
  include EM::Deferrable

  def initialize( name )
    @name = name
    callback do |who|              EM.run do
      puts "Approved #{who}!"        s1 = LoanRequest.new('Marc')
    end                              s1.approved!


    errback do |who|                 s2 = LoanRequest.new('Chris')
      puts "Denied #{who}!"          EM.add_timer(2){ s2.denied! }
    end                            end
  end

  def approved!
    # succeed( *args )
    set_deferred_status(:succeeded, @name)
  end

  def denied!
    # fail( *args )
    set_deferred_status(:failed, @name)
  end
end
class LoanRequest
  include EM::Deferrable

  def initialize( name )
    @name = name
    callback do |who|              EM.run do
      puts "Approved #{who}!"        s1 = LoanRequest.new('Marc')
    end                              s1.approved!


    errback do |who|                 s2 = LoanRequest.new('Chris')
      puts "Denied #{who}!"          EM.add_timer(2){ s2.denied! }
    end                            end
  end

  def approved!
    # succeed( *args )
    set_deferred_status(:succeeded, @name)
  end                                        # :00 Approved Marc!
                                             # :02 Denied Chris!
  def denied!
    # fail( *args )
    set_deferred_status(:failed, @name)
  end
end
state: nil
state: nil


callback{}

callback{}

callback{}
state: nil


callback{}                errback{}

callback{}                errback{}

callback{}
state: succeeded


callback{}                      errback{}

callback{}                      errback{}

callback{}
state: succeeded


callback{}

callback{}

callback{}
state: succeeded
state: failed


callback{}                   errback{}

callback{}                   errback{}

callback{}
state: failed


                errback{}

                errback{}
state: failed
class Mailer
  include EM::Deferrable

  def add_mailing(val)
    callback do
      sleep 1
      puts "Sent #{val}"
    end
  end

  def connection_open!
    puts 'Open connection'
    succeed
  end

  def connection_lost!
    puts 'Lost connection'
    set_deferred_status nil
  end
end
EM.run do
                                m = Mailer.new
class Mailer
                                m.add_mailing(1)
  include EM::Deferrable
                                m.add_mailing(2)
                                m.connection_open!
  def add_mailing(val)
    callback do
                                EM.add_timer(1) do
      sleep 1
                                  m.connection_lost!
      puts "Sent #{val}"
                                  EM.add_timer(2) do
    end
                                    m.add_mailing(3)
  end
                                    m.add_mailing(4)
                                    m.connection_open!
  def connection_open!
                                  end
    puts 'Open connection'
                                end
    succeed
                              end
  end

  def connection_lost!
    puts 'Lost connection'
    set_deferred_status nil
  end
end
EM.run do
                                m = Mailer.new
class Mailer
                                m.add_mailing(1)
  include EM::Deferrable
                                m.add_mailing(2)
                                m.connection_open!
  def add_mailing(val)
    callback do
                                EM.add_timer(1) do
      sleep 1
                                  m.connection_lost!
      puts "Sent #{val}"
                                  EM.add_timer(2) do
    end
                                    m.add_mailing(3)
  end
                                    m.add_mailing(4)
                                    m.connection_open!
  def connection_open!
                                  end
    puts 'Open connection'
                                end
    succeed
                              end
  end

  def connection_lost!                      #   Open   connection
    puts 'Lost connection'                  #   Sent   1
    set_deferred_status nil                 #   Sent   2
  end                                       #   Lost   connection
end                                         #   Open   connection
                                            #   Sent   3
                                            #   Sent   4
Gotchas

• Inverted flow of control can make
  debugging difficult
• Synchronous code will slow it down
 • Use/Write libraries for EM
Worth checking out

• EM-Synchrony:
  https://github.com/igrigorik/em-synchrony
• Goliath:
  https://github.com/postrank-labs/goliath
• Async_Sinatra:
  https://github.com/raggi/async_sinatra
Baie Dankie!
Questions?

Mais conteúdo relacionado

Mais procurados

Rust-lang
Rust-langRust-lang

Mais procurados (20)

Rust-lang
Rust-langRust-lang
Rust-lang
 
Rustlabs Quick Start
Rustlabs Quick StartRustlabs Quick Start
Rustlabs Quick Start
 
Rust Mozlando Tutorial
Rust Mozlando TutorialRust Mozlando Tutorial
Rust Mozlando Tutorial
 
Rust concurrency tutorial 2015 12-02
Rust concurrency tutorial 2015 12-02Rust concurrency tutorial 2015 12-02
Rust concurrency tutorial 2015 12-02
 
Ruby basics
Ruby basicsRuby basics
Ruby basics
 
Introduction to Rust
Introduction to RustIntroduction to Rust
Introduction to Rust
 
Ruby 2.0: to infinity... and beyond!
Ruby 2.0: to infinity... and beyond!Ruby 2.0: to infinity... and beyond!
Ruby 2.0: to infinity... and beyond!
 
Implementações paralelas
Implementações paralelasImplementações paralelas
Implementações paralelas
 
Douglas Crockford: Serversideness
Douglas Crockford: ServersidenessDouglas Crockford: Serversideness
Douglas Crockford: Serversideness
 
NativeBoost
NativeBoostNativeBoost
NativeBoost
 
Advanced Python, Part 1
Advanced Python, Part 1Advanced Python, Part 1
Advanced Python, Part 1
 
Lecture on Rubinius for Compiler Construction at University of Twente
Lecture on Rubinius for Compiler Construction at University of TwenteLecture on Rubinius for Compiler Construction at University of Twente
Lecture on Rubinius for Compiler Construction at University of Twente
 
Rust: Unlocking Systems Programming
Rust: Unlocking Systems ProgrammingRust: Unlocking Systems Programming
Rust: Unlocking Systems Programming
 
Introduction to Groovy
Introduction to GroovyIntroduction to Groovy
Introduction to Groovy
 
4Developers: Michał Szczepanik- Kotlin - Let’s ketchup it
4Developers: Michał Szczepanik- Kotlin - Let’s ketchup it4Developers: Michał Szczepanik- Kotlin - Let’s ketchup it
4Developers: Michał Szczepanik- Kotlin - Let’s ketchup it
 
Introduction to Rust language programming
Introduction to Rust language programmingIntroduction to Rust language programming
Introduction to Rust language programming
 
DRYing to Monad in Java8
DRYing to Monad in Java8DRYing to Monad in Java8
DRYing to Monad in Java8
 
Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015
 
Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)
 
Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)
 

Semelhante a EventMachine for RubyFuZa 2012

Ruby 程式語言入門導覽
Ruby 程式語言入門導覽Ruby 程式語言入門導覽
Ruby 程式語言入門導覽
Wen-Tien Chang
 
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
 

Semelhante a EventMachine for RubyFuZa 2012 (20)

Scaling Ruby with Evented I/O - Ruby underground
Scaling Ruby with Evented I/O - Ruby undergroundScaling Ruby with Evented I/O - Ruby underground
Scaling Ruby with Evented I/O - Ruby underground
 
Two Trains and Other Refactoring Analogies
Two Trains and Other Refactoring AnalogiesTwo Trains and Other Refactoring Analogies
Two Trains and Other Refactoring Analogies
 
Specs2
Specs2Specs2
Specs2
 
Servers with Event Machine - David Troy - RailsConf 2011
Servers with Event Machine - David Troy - RailsConf 2011Servers with Event Machine - David Troy - RailsConf 2011
Servers with Event Machine - David Troy - RailsConf 2011
 
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
 
Introduction to python programming ( part-2 )
Introduction to python programming ( part-2 )Introduction to python programming ( part-2 )
Introduction to python programming ( part-2 )
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
 
Pharo: Syntax in a Nutshell
Pharo: Syntax in a NutshellPharo: Syntax in a Nutshell
Pharo: Syntax in a Nutshell
 
Introducing Elixir and OTP at the Erlang BASH
Introducing Elixir and OTP at the Erlang BASHIntroducing Elixir and OTP at the Erlang BASH
Introducing Elixir and OTP at the Erlang BASH
 
Ruby 程式語言入門導覽
Ruby 程式語言入門導覽Ruby 程式語言入門導覽
Ruby 程式語言入門導覽
 
Symfony messenger - PHPers Summit 2019
Symfony messenger - PHPers Summit 2019Symfony messenger - PHPers Summit 2019
Symfony messenger - PHPers Summit 2019
 
Ruby Intro {spection}
Ruby Intro {spection}Ruby Intro {spection}
Ruby Intro {spection}
 
Nick Sieger JRuby Concurrency EMRubyConf 2011
Nick Sieger JRuby Concurrency EMRubyConf 2011Nick Sieger JRuby Concurrency EMRubyConf 2011
Nick Sieger JRuby Concurrency EMRubyConf 2011
 
Postobjektové programovanie v Ruby
Postobjektové programovanie v RubyPostobjektové programovanie v Ruby
Postobjektové programovanie v Ruby
 
Why Task Queues - ComoRichWeb
Why Task Queues - ComoRichWebWhy Task Queues - ComoRichWeb
Why Task Queues - ComoRichWeb
 
Async History - javascript
Async History - javascriptAsync History - javascript
Async History - javascript
 
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RIThe Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
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...
 

Último

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
vu2urc
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 

Último (20)

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
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
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
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
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
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 

EventMachine for RubyFuZa 2012

  • 1. EventMachine EM.run{ awesome_stuff! } Christopher Spring
  • 3.
  • 4.
  • 7. • Mostly IO bound • Handle thousands concurrent connections • Stream data • Real time data delivery • You’ve got Mad Ruby Skills
  • 8. What is EventMachine? • Toolkit for creating evented applications • Implementation of the Reactor Pattern • MRI,YARV, jRuby, Rubinius
  • 11. Evented? puts(1) puts(2) puts(3) puts(1) work{ puts(3) } puts(2)
  • 12. Reactor pattern “Event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers.” http://en.wikipedia.org/wiki/Reactor_pattern
  • 13. Http Keyboard Udp etc Service handler Demultiplexer Event dispatcher Event Handler A Event Handler B Event Handler C Event Handler D
  • 14. Http Keyboard Udp etc Service handler Demultiplexer Event dispatcher Event Handler A Event Handler B Event Handler C Event Handler D
  • 15. Http Keyboard Udp etc Service handler Demultiplexer Event dispatcher Thread 1 Event Handler A Thread 2 Event Handler B ... Event Handler C Event Handler D Thread 20
  • 16. Benefits • Application code separate from reactor • Non blocking IO • Single process • No threads!
  • 17. Limitations • Demultiplexing limits • Some others we’ll cover later...
  • 18. Teh Basics • EM.run • EM.connection • EM.next_tick • EM.defer • EM::Queue • EM::Channel
  • 19. Teh Basics • EM.run • EM.connection • EM.next_tick • EM.defer • EM::Queue • EM::Channel
  • 21. ... don’t do this! • big ass loops • 1_000_000.times{} • while condition? • sleep • blocking IO
  • 22. Teh Basics • EM.run • EM.connection • EM.next_tick • EM.defer • EM::Queue • EM::Channel
  • 23. class EchoServer < EM::Connection def post_init puts "New connection" end def unbind puts "Connection closed" end def receive_data(data) send_data ">> #{data}" end end EM.run do EM.start_server('127.0.0.1', 9000, EchoServer) puts "Started server at 127.0.0.1:9000" end
  • 24. class EchoServer < EM::Connection def post_init puts "New connection" end def unbind puts "Connection closed" # $ telnet localhost 9000 end # Hello # >> Hello def receive_data(data) # Bye send_data ">> #{data}" # >> Bye end end EM.run do EM.start_server('127.0.0.1', 9000, EchoServer) puts "Started server at 127.0.0.1:9000" end
  • 25. # TCP EM.run do EM.start_server('127.0.0.1', 9000, EchoServer) end # UDP EM.run do EM.open_datagram_socket('127.0.0.1', 9000, EchoServer) end # Unix-domain server EM.run do EM.start_unix_domain_server('/tmp/sock', nil, EchoServer) end
  • 26. class EchoClient < EM::Connection def post_init puts "Sending stuff to server" send_data("Why, hello there!") end def unbind puts "Connection closed" end def receive_data(data) puts ">> #{data}" end end EM.run do EM.connect('127.0.0.1', 9000, EchoClient) end
  • 27. class EchoClient < EM::Connection def post_init puts "Sending stuff to server" send_data("Why, hello there!") end def unbind puts "Connection closed" end def receive_data(data) puts ">> #{data}" end end EM.run do EM.connect('127.0.0.1', 9000, EchoClient) end
  • 28. Teh Basics • EM.run • EM.connection • EM.next_tick • EM.defer • EM::Queue • EM::Channel
  • 29. EM.run do EM.next_tick do # ... awesome stuff end end
  • 31. Task 1 Task 2 Task 3 EM.run{ }
  • 32. Task 1 Task 2 Task 3 EM.run{ } EM.next_tick{ }
  • 33. Teh Basics • EM.run • EM.connection • EM.next_tick • EM.defer • EM::Queue • EM::Channel
  • 34. EM.run do EM.defer do send_email( user1 ) end EM.defer do send_email( user2 ) end EM.defer do send_email( user3 ) end end
  • 36. Email 1 Email 2 Email 3 EM.defer{ }
  • 37. EM.run do get_stuff = Proc.new do # ... long_running_io() end use_stuff = Proc.new do |io_results| # ... end # ... EM.defer( get_stuff, use_stuff ) end
  • 38. Teh Basics • EM.run • EM.connection • next_tick; add_timer; add_periodic_timer • EM.defer • EM::Queue • EM::Channel
  • 39. EM.run do queue = EM::Queue.new # ... queue.push( data1, data2 ) # ... queue.pop { |data| puts data } # >> data1 end
  • 40. EM.run do queue = EM::Queue.new EM.defer do sleep( 2 ) queue.push( 'some@email.com' ) sleep( 3 ) queue.push( 'some@one.com') end welcomer = Proc.new do |email| send_welcome( email ) EM.next_tick( queue.pop(&welcomer) ) end queue.pop(&welcomer); end
  • 41. Teh Basics • EM.run • EM.connection • EM.next_tick • EM.defer • EM::Queue • EM::Channel
  • 42. EM.run do channel = EM::Channel.new EM.defer do channel.subscribe do |msg| puts "Received #{msg}" end end EM.add_periodic_timer(1) do channel << Time.now end end
  • 43. Deferrable • Light weight concurrency • Delayed execution with triggers • :succeeded • :failed • nil • callback and errback
  • 44. class LoanRequest include EM::Deferrable def initialize( name ) @name = name callback do |who| puts "Approved #{who}!" end errback do |who| puts "Denied #{who}!" end end def approved! # succeed( *args ) set_deferred_status(:succeeded, @name) end def denied! # fail( *args ) set_deferred_status(:failed, @name) end end
  • 45. class LoanRequest include EM::Deferrable def initialize( name ) @name = name callback do |who| EM.run do puts "Approved #{who}!" s1 = LoanRequest.new('Marc') end s1.approved! errback do |who| s2 = LoanRequest.new('Chris') puts "Denied #{who}!" EM.add_timer(2){ s2.denied! } end end end def approved! # succeed( *args ) set_deferred_status(:succeeded, @name) end def denied! # fail( *args ) set_deferred_status(:failed, @name) end end
  • 46. class LoanRequest include EM::Deferrable def initialize( name ) @name = name callback do |who| EM.run do puts "Approved #{who}!" s1 = LoanRequest.new('Marc') end s1.approved! errback do |who| s2 = LoanRequest.new('Chris') puts "Denied #{who}!" EM.add_timer(2){ s2.denied! } end end end def approved! # succeed( *args ) set_deferred_status(:succeeded, @name) end # :00 Approved Marc! # :02 Denied Chris! def denied! # fail( *args ) set_deferred_status(:failed, @name) end end
  • 49. state: nil callback{} errback{} callback{} errback{} callback{}
  • 50. state: succeeded callback{} errback{} callback{} errback{} callback{}
  • 53. state: failed callback{} errback{} callback{} errback{} callback{}
  • 54. state: failed errback{} errback{}
  • 56. class Mailer include EM::Deferrable def add_mailing(val) callback do sleep 1 puts "Sent #{val}" end end def connection_open! puts 'Open connection' succeed end def connection_lost! puts 'Lost connection' set_deferred_status nil end end
  • 57. EM.run do m = Mailer.new class Mailer m.add_mailing(1) include EM::Deferrable m.add_mailing(2) m.connection_open! def add_mailing(val) callback do EM.add_timer(1) do sleep 1 m.connection_lost! puts "Sent #{val}" EM.add_timer(2) do end m.add_mailing(3) end m.add_mailing(4) m.connection_open! def connection_open! end puts 'Open connection' end succeed end end def connection_lost! puts 'Lost connection' set_deferred_status nil end end
  • 58. EM.run do m = Mailer.new class Mailer m.add_mailing(1) include EM::Deferrable m.add_mailing(2) m.connection_open! def add_mailing(val) callback do EM.add_timer(1) do sleep 1 m.connection_lost! puts "Sent #{val}" EM.add_timer(2) do end m.add_mailing(3) end m.add_mailing(4) m.connection_open! def connection_open! end puts 'Open connection' end succeed end end def connection_lost! # Open connection puts 'Lost connection' # Sent 1 set_deferred_status nil # Sent 2 end # Lost connection end # Open connection # Sent 3 # Sent 4
  • 59. Gotchas • Inverted flow of control can make debugging difficult • Synchronous code will slow it down • Use/Write libraries for EM
  • 60. Worth checking out • EM-Synchrony: https://github.com/igrigorik/em-synchrony • Goliath: https://github.com/postrank-labs/goliath • Async_Sinatra: https://github.com/raggi/async_sinatra
  • 61.

Notas do Editor

  1. \n
  2. \n
  3. ScaleConf: Doing anything at scale requires better decisions about the tools you use.\nJust because the fit seemed ok at first, when things get rolling you really want to have the right kind of hammer.\n
  4. ... and to achieve dramatic results, you need to orchestrate a specialized set of components\n\ncomplexity is a tradeoff based on the domain of your problem.\n
  5. \n
  6. \n
  7. c10k problem\n
  8. c++ reactor: mri, yarv, Rubinius\n\njava reactor for, um, java\n
  9. used to sequential code\nevented code stores some block...\nand executes at some later stage\n
  10. used to sequential code\nevented code stores some block...\nand executes at some later stage\n
  11. \n
  12. Input is received concurrently\nEvent dispatch is synchronous\nThe reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers\n\n
  13. Input is received concurrently\nEvent dispatch is synchronous\nThe reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers\n\n
  14. Input is received concurrently\nEvent dispatch is synchronous\nThe reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers\n\n
  15. Input is received concurrently\nEvent dispatch is synchronous\nThe reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers\n\n
  16. Input is received concurrently\nEvent dispatch is synchronous\nThe reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers\n\n
  17. Input is received concurrently\nEvent dispatch is synchronous\nThe reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers\n\n
  18. \n
  19. Limitations ito select/epoll and the number of open file descriptors\n\n&amp;#x201C;First, you need to tell EventMachine to use epoll instead of select. Second, you need to prepare your program to use more than 1024 descriptors, an operation that generally requires superuser privileges. Third, you will probably want your process to drop the superuser privileges after you increase your process&amp;#x2019;s descriptor limit.&amp;#x201D; - See: http://eventmachine.rubyforge.org/docs/EPOLL.html\n
  20. connection -&gt; servers and clients and shit\nnext_tick -&gt; run code at the next opportunity (always run in main thread)\ndefer -&gt; defer work to run on a thread (green) - 20 by default\nQueue -&gt; data\nChannel -&gt; comms\n
  21. next_tick -&gt; run code at the next opportunity (always run in main thread)\ndefer -&gt; defer work to run on a thread (green) - 20 by default\nQueue -&gt; data\nChannel -&gt; comms\n
  22. Main reactor is single threaded - similar to while reactor_running?; ... end\nEM.run takes over the process...\nit&amp;#x2019;s blocking\n\n
  23. ... anything that blocks the main reactor is a no-no\n\nAnything that takes more than a few millisecond...\nrun on separate thread or broken into smaller blocks...\nand run on next_tick\n
  24. Used for creating clients and servers\n
  25. EM interchangeable with EventMachine\nreceive_data is unbuffered\nthese methods are the only ones that will be called by the event loop\n\ncan have a module, and it&amp;#x2019;s behaviour will be mixed into an EM:: Connection\n
  26. \n
  27. EM interchangeable with EventMachine\nreceive_data is unbuffered\n
  28. Schedules work to happen on the main thread\non the next iteration of the reactor\n
  29. Next tick is a tool for bringing data/work back into the run loop\n\nUm, wtf for? You may find yourself asking...\n
  30. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  31. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  32. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  33. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  34. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  35. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  36. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  37. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  38. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  39. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  40. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  41. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  42. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  43. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  44. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  45. Tasks are not broken up into smaller pieces\n... takes really long to complete task 2 and 3\nDo very little work in the main reactor\n
  46. schedules work to take place on a different thread\n
  47. defer runs on thread in thread pool (20 by default)\n
  48. defer allows work to be done on one of the thread pool threads\n
  49. defer allows work to be done on one of the thread pool threads\n
  50. defer allows work to be done on one of the thread pool threads\n
  51. defer allows work to be done on one of the thread pool threads\n
  52. get_stuff run in separate thread,\nData is brought back to the main thread\nand passed on to the callback\nCallback executes on the main thread\nKinda like a future\n
  53. Ordered message queue\nThread safe\n
  54. Popped data is brought back to the main thread\npush/pop scheduled next iteration of the main reactor thread\n
  55. Infinite processing - always do work if there is some available\ndata pops off the queue only when data is available (no blocking)\n\n
  56. next_tick -&gt; run code at the next opportunity (always run in main thread)\ndefer -&gt; defer work to run on a thread (green) - 20 by default\nQueue -&gt; data\nChannel -&gt; comms\n
  57. Pub/Sub mechanism\n
  58. :succeeded -&gt; callback\n:failed -&gt; errback\nnil -&gt; reset (slate wiped clean)\n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. errbacks are trashed\ncallbacks are executed immediately in the order they were added\n
  69. errbacks are trashed\ncallbacks are executed immediately in the order they were added\n
  70. errbacks are trashed\ncallbacks are executed immediately in the order they were added\n
  71. errbacks are trashed\ncallbacks are executed immediately in the order they were added\n
  72. errbacks are trashed\ncallbacks are executed immediately in the order they were added\n
  73. callbacks are trashed\nerrbacks are executed immediately in the order they were added\n
  74. callbacks are trashed\nerrbacks are executed immediately in the order they were added\n
  75. callbacks are trashed\nerrbacks are executed immediately in the order they were added\n
  76. callbacks are trashed\nerrbacks are executed immediately in the order they were added\n
  77. callbacks are trashed\nerrbacks are executed immediately in the order they were added\n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n\n
  85. \n
  86. \n