SlideShare a Scribd company logo
Building Scalable Servers
With EventMachine and Rails


                               Dave Troy
                               Chief Executive Officer



      davetroy@shortmail.com

      @davetroy

      facebook.com/davetroy
Servers with Event Machine - David Troy - RailsConf 2011
EventMachine
EventMachine

    DRY
EventMachine

    DRY
   DRAG
EventMachine

          DRY
          DRAG
(Don’t Repeat Aman Gupta)
require ‘aman_gupta’
EventMachine
scalable non-blocking i/o in ruby
About Me
Aman Gupta
San Francisco, CA
Been maintaining EventMachine for 18
months (last 4 releases)
Ruby Hero 2009
amqp, REE patches, perftools.rb, gdb.rb,
memprof
github.com/tmm1
@tmm1
What is EventMachine?
Implementation of the Reactor pattern
  similar to Python’s Twisted   also node.js, libev
Ruby VM Support
  Ruby 1.8 (MRI)
  Ruby 1.9 (YARV)                         c++ reactor
  Rubinius
  JRuby                                   java reactor
  + simple Pure Ruby version
What is I/O?
 Generally Network I/O
   mysql query responses
   http responses
   memcache results

 Most web applications are I/O bound, not CPU bound
 Basic idea behind EM: Instead of waiting on a response
 from the network, use that time to process other
 requests
What can I use EM for?
Scaling I/O heavy applications
  handle 5-10k concurrent connections with a single
  ruby process
Any type of network I/O
  http requests
  sending emails
  custom tcp proxies
  data access
    redis
    couchdb
    mysql
    postgres
    casandra
    memcached
Simple TCP Server
TCPServer#accept     require 'socket'
                     server = TCPServer.new(2202)
to accept
                     while client = server.accept
connections from       msg = client.readline
new clients            client.write "You said: #{msg}"
                       client.close
TCPSocket#read*      end

blocks, so you can
                     require 'socket'
only handle one      server = TCPServer.new(2202)
client at a time     while true
                       Thread.new(server.accept){ |client|
Common Solution:         msg = client.readline
                         client.write "You said: #{msg}"
use a thread per         client.close
client                 }
                     end
require 'socket'
 inbound                         server = TCPServer.new(2202)
               list of clients   clients = []
buffer per                       buffers = {}


     client IO.select returns    while true
                                   sockets = [server] + clients
            readable/writable      readable, writable = IO.select(sockets)


                       sockets    readable.each do |sock|
                                    begin
                                      if sock == server
                                        clients << server.accept_nonblock
                                      else
                                        client, buf = sock, buffers[sock] ||= ''
    read in available data,
                                         buf << client.read_nonblock(1024)
process if full line received            if buf =~ /^.+?r?n/
                                           client.write "You said: #{buf}"



  Non-Blocking I/O
                                           client.close

                                           buffers.delete(client)
                                           clients.delete(client)
                                         end
    Alternative to                     end
                                     rescue Errno::EAGAIN, Errno::EWOULDBLOCK
    threads: simply don’t              # socket would block, try again later
                                     end
    block                          end
                                 end
EM does Non-Blocking I/O
handles low         module EchoServer
level sockets         def post_init
for you                 @buf = ''
                      end
inbound/              def receive_data(data)
                        @buf << data
outbound                if @buf =~ /^.+?r?n/
buffers for               send_data "You said: #{@buf}"
                          close_connection_after_writing
maximal                 end
throughput            end
                    end
efficient i/o with
writev/readv        require 'eventmachine'
                    EM.run do
                      EM.start_server '0.0.0.0', 2202, EchoServer
epoll & kqueue      end
support
So, what’s a Reactor?
       while reactor_running?
         expired_timers.each{ |timer| timer.process }
         new_network_io.each{ |io| io.process }
       end

reactor is simply a single threaded while loop, called
the “reactor loop”
your code “reacts” to incoming events
if your event handler takes too long, other events
cannot fire
lesson: never block the reactor        while reactor_running?
                                         while true
   no sleep(1)                           end
   no long loops (100_000.times)         # reactor is blocked!
   no blocking I/O (mysql queries)     end
   no polling (while !condition)
Writing Asynchronous Code
synchronous ruby code uses return values
            ret = operation()
            do_something_with(ret)

evented async code uses blocks instead
operation{ |ret| do_something_with(ret) }

different from how you usually use ruby blocks. the block
is stored and invoked later (it’s asynchronous)
puts(1)                      puts(1)
1.times{ puts(2) }           operation{ puts(3) }
puts(3)                      puts(2)
Receiving Email Using ActionMailer

  port 25        postfix
  (smtp)         (spool)

                        fork
                      process


                 Action                   pgsql
                 Mailer    ActiveRecord    (db)
Receiving Email Using LMTP

  port 25       postfix
  (smtp)        (spool)

                     port 8081
                      (lmtp)


                 EM                       pgsql
               (w/Rails)   ActiveRecord    (db)
Receiving Email — Scalably via LMTP


    postfix       postfix       message
    (spool)       (spool)       systems




     EM          EM           EM          EM
   (w/Rails)   (w/Rails)    (w/Rails)   (w/Rails)
LMTP Daemon



http://tools.ietf.org/html/rfc2033
POP3 Daemon



http://tools.ietf.org/html/rfc1939
IMAP Daemon



http://tools.ietf.org/html/rfc3501
EventMachine
Geo Firehose                       LISTEN
                                    8192
(one connection - Port 80)


                                      250, 500, 1000 Connections

 twittervision.com/
                                Apache
       stream

RewriteRule ^/stream(.*)$ http://127.0.0.1:8192%{REQUEST_URI} [P,QSA,L]
replyz.com
Does Anybody Know...?

mailstrom.co
mailstrom.410labs.com
Power Tools for Your Inbox

shortmail.com
Email, simplified.
Some Other Handy Stuff...

  • start_tls: secure any TCP connection
  • Timers: Periodic, Once, Scheduled
  • epoll, kqueue, threadpool_size
  • set_effective_user             (listen on protected ports)



  • teh docs: http://eventmachine.rubyforge.org/EventMachine.html
So, Some Stuff To Remember...

  • EventMachine: awesome for I/O, events
  • Code is Data, Data is Code
  • Often Working with State Machines
  • Don’t peg the CPU. No really, don’t.
  • TEBWTDI
  • Testing can be interesting
Dave Troy
                             Chief Executive Officer



    davetroy@shortmail.com

    @davetroy

    facebook.com/davetroy




 Tomorrow @ BohConf!
http://emrubyconf.com/

More Related Content

PPT
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
PPTX
Ruby Proxies for Scale, Performance, and Monitoring
PPTX
Event Driven Architecture - MeshU - Ilya Grigorik
PPTX
Ruby C10K: High Performance Networking - RubyKaigi '09
KEY
Streams are Awesome - (Node.js) TimesOpen Sep 2012
PDF
Communication in Python and the C10k problem
PPTX
No Callbacks, No Threads - RailsConf 2010
PDF
Scaling Ruby with Evented I/O - Ruby underground
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
Ruby Proxies for Scale, Performance, and Monitoring
Event Driven Architecture - MeshU - Ilya Grigorik
Ruby C10K: High Performance Networking - RubyKaigi '09
Streams are Awesome - (Node.js) TimesOpen Sep 2012
Communication in Python and the C10k problem
No Callbacks, No Threads - RailsConf 2010
Scaling Ruby with Evented I/O - Ruby underground

What's hot (20)

PDF
Solving some of the scalability problems at booking.com
PDF
Using Node.js to Build Great Streaming Services - HTML5 Dev Conf
KEY
A language for the Internet: Why JavaScript and Node.js is right for Internet...
PPT
Server side JavaScript: going all the way
PDF
Nodejs Explained with Examples
PDF
WebSockets with Spring 4
KEY
Concurrency in ruby
PDF
Non-blocking I/O, Event loops and node.js
PPT
JavaScript Event Loop
PDF
Node.js streaming csv downloads proxy
PDF
Nginx وب سروری برای تمام فصول
PPT
Ruby vs Node ShiningRay Shanghai
KEY
A million connections and beyond - Node.js at scale
PDF
Comet with node.js and V8
PDF
vert.x 3.1 - be reactive on the JVM but not only in Java
PDF
Testing applications with traffic control in containers / Alban Crequy (Kinvolk)
PPT
Node js presentation
PDF
An Introduction to Twisted
KEY
Writing robust Node.js applications
KEY
Ruby Concurrency and EventMachine
Solving some of the scalability problems at booking.com
Using Node.js to Build Great Streaming Services - HTML5 Dev Conf
A language for the Internet: Why JavaScript and Node.js is right for Internet...
Server side JavaScript: going all the way
Nodejs Explained with Examples
WebSockets with Spring 4
Concurrency in ruby
Non-blocking I/O, Event loops and node.js
JavaScript Event Loop
Node.js streaming csv downloads proxy
Nginx وب سروری برای تمام فصول
Ruby vs Node ShiningRay Shanghai
A million connections and beyond - Node.js at scale
Comet with node.js and V8
vert.x 3.1 - be reactive on the JVM but not only in Java
Testing applications with traffic control in containers / Alban Crequy (Kinvolk)
Node js presentation
An Introduction to Twisted
Writing robust Node.js applications
Ruby Concurrency and EventMachine
Ad

Similar to Servers with Event Machine - David Troy - RailsConf 2011 (20)

PDF
Python twisted
KEY
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
PDF
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
PDF
Anchoring Trust: Rewriting DNS for the Semantic Network with Ruby and Rails
PDF
Rhebok, High Performance Rack Handler / Rubykaigi 2015
ODP
Pfm technical-inside
PDF
Dragoncraft Architectural Overview
PDF
Tornado Web Server Internals
PPTX
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
PDF
CODE FOR echo_client.c A simple echo client using TCP #inc.pdf
PDF
Torquebox OSCON Java 2011
KEY
A language for the Internet: Why JavaScript and Node.js is right for Internet...
PPT
KEY
TorqueBox - Ruby Hoedown 2011
ODP
Node js lecture
PDF
Scalable Socket Server by Aryo
PPT
03 sockets
PDF
JUDCon 2010 Boston : TorqueBox
PDF
How to Leverage Go for Your Networking Needs
PDF
Python twisted
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
Anchoring Trust: Rewriting DNS for the Semantic Network with Ruby and Rails
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Pfm technical-inside
Dragoncraft Architectural Overview
Tornado Web Server Internals
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
CODE FOR echo_client.c A simple echo client using TCP #inc.pdf
Torquebox OSCON Java 2011
A language for the Internet: Why JavaScript and Node.js is right for Internet...
TorqueBox - Ruby Hoedown 2011
Node js lecture
Scalable Socket Server by Aryo
03 sockets
JUDCon 2010 Boston : TorqueBox
How to Leverage Go for Your Networking Needs
Ad

Recently uploaded (20)

PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Empathic Computing: Creating Shared Understanding
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PPTX
Big Data Technologies - Introduction.pptx
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Encapsulation theory and applications.pdf
PDF
Assigned Numbers - 2025 - Bluetooth® Document
PPTX
Tartificialntelligence_presentation.pptx
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PPTX
A Presentation on Artificial Intelligence
PDF
Getting Started with Data Integration: FME Form 101
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PPTX
Machine Learning_overview_presentation.pptx
Advanced methodologies resolving dimensionality complications for autism neur...
Empathic Computing: Creating Shared Understanding
Digital-Transformation-Roadmap-for-Companies.pptx
Big Data Technologies - Introduction.pptx
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Network Security Unit 5.pdf for BCA BBA.
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Per capita expenditure prediction using model stacking based on satellite ima...
Building Integrated photovoltaic BIPV_UPV.pdf
The Rise and Fall of 3GPP – Time for a Sabbatical?
Encapsulation theory and applications.pdf
Assigned Numbers - 2025 - Bluetooth® Document
Tartificialntelligence_presentation.pptx
Dropbox Q2 2025 Financial Results & Investor Presentation
A Presentation on Artificial Intelligence
Getting Started with Data Integration: FME Form 101
Diabetes mellitus diagnosis method based random forest with bat algorithm
Unlocking AI with Model Context Protocol (MCP)
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Machine Learning_overview_presentation.pptx

Servers with Event Machine - David Troy - RailsConf 2011

  • 1. Building Scalable Servers With EventMachine and Rails Dave Troy Chief Executive Officer [email protected] @davetroy facebook.com/davetroy
  • 5. EventMachine DRY DRAG
  • 6. EventMachine DRY DRAG (Don’t Repeat Aman Gupta)
  • 9. About Me Aman Gupta San Francisco, CA Been maintaining EventMachine for 18 months (last 4 releases) Ruby Hero 2009 amqp, REE patches, perftools.rb, gdb.rb, memprof github.com/tmm1 @tmm1
  • 10. What is EventMachine? Implementation of the Reactor pattern similar to Python’s Twisted also node.js, libev Ruby VM Support Ruby 1.8 (MRI) Ruby 1.9 (YARV) c++ reactor Rubinius JRuby java reactor + simple Pure Ruby version
  • 11. What is I/O? Generally Network I/O mysql query responses http responses memcache results Most web applications are I/O bound, not CPU bound Basic idea behind EM: Instead of waiting on a response from the network, use that time to process other requests
  • 12. What can I use EM for? Scaling I/O heavy applications handle 5-10k concurrent connections with a single ruby process Any type of network I/O http requests sending emails custom tcp proxies data access redis couchdb mysql postgres casandra memcached
  • 13. Simple TCP Server TCPServer#accept require 'socket' server = TCPServer.new(2202) to accept while client = server.accept connections from msg = client.readline new clients client.write "You said: #{msg}" client.close TCPSocket#read* end blocks, so you can require 'socket' only handle one server = TCPServer.new(2202) client at a time while true Thread.new(server.accept){ |client| Common Solution: msg = client.readline client.write "You said: #{msg}" use a thread per client.close client } end
  • 14. require 'socket' inbound server = TCPServer.new(2202) list of clients clients = [] buffer per buffers = {} client IO.select returns while true sockets = [server] + clients readable/writable readable, writable = IO.select(sockets) sockets readable.each do |sock| begin if sock == server clients << server.accept_nonblock else client, buf = sock, buffers[sock] ||= '' read in available data, buf << client.read_nonblock(1024) process if full line received if buf =~ /^.+?r?n/ client.write "You said: #{buf}" Non-Blocking I/O client.close buffers.delete(client) clients.delete(client) end Alternative to end rescue Errno::EAGAIN, Errno::EWOULDBLOCK threads: simply don’t # socket would block, try again later end block end end
  • 15. EM does Non-Blocking I/O handles low module EchoServer level sockets def post_init for you @buf = '' end inbound/ def receive_data(data) @buf << data outbound if @buf =~ /^.+?r?n/ buffers for send_data "You said: #{@buf}" close_connection_after_writing maximal end throughput end end efficient i/o with writev/readv require 'eventmachine' EM.run do EM.start_server '0.0.0.0', 2202, EchoServer epoll & kqueue end support
  • 16. So, what’s a Reactor? while reactor_running? expired_timers.each{ |timer| timer.process } new_network_io.each{ |io| io.process } end reactor is simply a single threaded while loop, called the “reactor loop” your code “reacts” to incoming events if your event handler takes too long, other events cannot fire lesson: never block the reactor while reactor_running? while true no sleep(1) end no long loops (100_000.times) # reactor is blocked! no blocking I/O (mysql queries) end no polling (while !condition)
  • 17. Writing Asynchronous Code synchronous ruby code uses return values ret = operation() do_something_with(ret) evented async code uses blocks instead operation{ |ret| do_something_with(ret) } different from how you usually use ruby blocks. the block is stored and invoked later (it’s asynchronous) puts(1) puts(1) 1.times{ puts(2) } operation{ puts(3) } puts(3) puts(2)
  • 18. Receiving Email Using ActionMailer port 25 postfix (smtp) (spool) fork process Action pgsql Mailer ActiveRecord (db)
  • 19. Receiving Email Using LMTP port 25 postfix (smtp) (spool) port 8081 (lmtp) EM pgsql (w/Rails) ActiveRecord (db)
  • 20. Receiving Email — Scalably via LMTP postfix postfix message (spool) (spool) systems EM EM EM EM (w/Rails) (w/Rails) (w/Rails) (w/Rails)
  • 24. EventMachine Geo Firehose LISTEN 8192 (one connection - Port 80) 250, 500, 1000 Connections twittervision.com/ Apache stream RewriteRule ^/stream(.*)$ http://127.0.0.1:8192%{REQUEST_URI} [P,QSA,L]
  • 25. replyz.com Does Anybody Know...? mailstrom.co mailstrom.410labs.com Power Tools for Your Inbox shortmail.com Email, simplified.
  • 26. Some Other Handy Stuff... • start_tls: secure any TCP connection • Timers: Periodic, Once, Scheduled • epoll, kqueue, threadpool_size • set_effective_user (listen on protected ports) • teh docs: http://eventmachine.rubyforge.org/EventMachine.html
  • 27. So, Some Stuff To Remember... • EventMachine: awesome for I/O, events • Code is Data, Data is Code • Often Working with State Machines • Don’t peg the CPU. No really, don’t. • TEBWTDI • Testing can be interesting
  • 28. Dave Troy Chief Executive Officer [email protected] @davetroy facebook.com/davetroy Tomorrow @ BohConf! http://emrubyconf.com/

Editor's Notes