SlideShare a Scribd company logo
1 of 108
Download to read offline
Reactor Pattern
                       &

Event-Driven Programming
   A scalable concurrent approach,
   using EventMachine with Thin as an example




                                            Lin Jen-Shin, http://godfat.org/
Reactor Pattern
                       &

Event-Driven Programming
   A scalable concurrent approach,
   using EventMachine with Thin as an example




                                            Lin Jen-Shin, http://godfat.org/
Reactor Pattern
                             &

     Event-Driven Programming
http://godfat.org/slide/2010-04-13-reactor-pattern-and-2.pdf




                                              Lin Jen-Shin, http://godfat.org/
Table of Contents
ā€¢ concurrency, why and how in network
ā€¢ Event-Driven Programming explained in
  Flash with Ruby syntax

ā€¢ Reactor Pattern in EventMachine with Thin
ā€¢ how Thin works
ā€¢ how EventMachine works
Event-Driven Programming
                        register method(:do_something)
loop{                   loop{
  # you control the flow # event loop control the flow,
  do_something            # later it calls your callback
}                         event = pop_event_queue
                          dispatch event if event
                        }
Reactor Pattern
                register method(:handle)
loop{           loop{
  data = read     data = partial_read
  handle data     event = process data
}                 dispatch event if event
                }
Table of Contents




ā€¢ how Thin works
ā€¢ how EventMachine works
Table of Contents

ā€¢ how Thin works
ā€¢ how EventMachine works
Table of Contents

ā€¢ how Thin works
ā€¢ how EventMachine works
ā€¢ how AMQP works
Table of Contents

ā€¢ how Thin works
ā€¢ how EventMachine works
ā€¢ how AMQP works
ā€¢ how Unicorn and Rainbows! works
Reactor Pattern
Request
(resource)
Reactor Pattern
                  EventMachine
Request
                  (demultiplexer
(resource)
                   + dispatcher)
Reactor Pattern
                  EventMachine
Request                            Thin (or AMQP)
                  (demultiplexer
(resource)                         (request handler)
                   + dispatcher)
Reactor Pattern
                  EventMachine
Request                                Thin (or AMQP)
                  (demultiplexer
(resource)                             (request handler)
                   + dispatcher)




                                   Rack Thin
                                    handler
Reactor Pattern
                     EventMachine
Request                                         Thin (or AMQP)
                      (demultiplexer
(resource)                                      (request handler)
                       + dispatcher)




                Rack Rails                  Rack Thin
                                 rack env
                 adapter                     handler
Reactor Pattern
                             EventMachine
        Request                                         Thin (or AMQP)
                              (demultiplexer
        (resource)                                      (request handler)
                               + dispatcher)




                        Rack Rails                  Rack Thin
Rails                                    rack env
                         adapter                     handler
your rails
application
                        Reactor Pattern
                                EventMachine
           Request                                         Thin (or AMQP)
                                 (demultiplexer
           (resource)                                      (request handler)
                                  + dispatcher)




                           Rack Rails                  Rack Thin
   Rails                                    rack env
                            adapter                     handler
how Thin works


                 Thin (or AMQP)
                 (request handler)
how Thin works
ā€¢ Thin::Server
how Thin works
ā€¢ Thin::Server
ā€¢ Thin::Backends::TcpServer
 # communicate with EventMachine
how Thin works
ā€¢ Thin::Server
ā€¢ Thin::Backends::TcpServer
 # communicate with EventMachine

ā€¢ Thin::Connection
 # EventMachine event handler
how Thin works
ā€¢ Thin::Server
ā€¢ Thin::Backends::TcpServer
 # communicate with EventMachine

ā€¢ Thin::Connection
 # EventMachine event handler

ā€¢ Thin::Request
 # partial HTTP request parsing
 # Rack env builder
how Thin works
Thin::Server
how Thin works
Thin::Server


           Backends::TcpServer
how Thin works
Thin::Server


           Backends::TcpServer




       Connection
how Thin works
Thin::Server


           Backends::TcpServer




       Connection


          Request
how Thin works
Thin::Server


           Backends::TcpServer




       Connection
               Connection


          Request Request
how Thin works
Thin::Server


           Backends::TcpServer




       Connection
               Connection
                       Connection


          Request Request Request
how Thin works
    thin 1.2.7 codename No Hup
how Thin works
              thin 1.2.7 codename No Hup

# in lib/thin/backends/tcp_server.rb:16
# in Thin::TcpServer#connect

  EventMachine.start_server(
    @host, @port,
    Thin::Connection,
    &method(:initialize_connection))

         # rack app, backend ref, timeout, etc
how Thin works
              thin 1.2.7 codename No Hup

# in lib/thin/connection.rb:42
# in Thin::Connection#receive_data


    process if @request.parse(data)


             # true: parsed, so process!
             # false: we need more data!
how Thin works
                   thin 1.2.7 codename No Hup

     # in lib/thin/request.rb:82
     # in Thin::Request#parse


@request = @parser.execute(@env, @data, @nparsed)


                   #     @env: Rack env
                   #    @data: HTTP header buffer
                   # @nparsed: index of parsed data
how Thin works
                     thin 1.2.7 codename No Hup

     // in ext/thin_parser/thin.c:335
     // in thin.c#Thin_HttpParser_execute


thin_http_parser_execute(http, dptr, dlen, from);


                //   http:   HTTP parser pointer
                //   dptr:   HTTP header data pointer
                //   dlen:   HTTP header data length
                //   form:   previous @nparsed
how Thin works
                   thin 1.2.7 codename No Hup
     // in ext/thin_parser/parser.rl:102
     // in parser.rl#thin_http_parser_execute
     // (itā€™s mongrelā€™s http parser)

size_t thin_http_parser_execute(
  http_parser *parser, const char *buffer,
  size_t len, size_t off)
how Thin works
                  thin 1.2.7 codename No Hup

Ragel is a ļ¬nite state machine compiler with
output support for C, C++, Objective-C, D, Java
and Ruby source code.
how Thin works
                  thin 1.2.7 codename No Hup

Ragel is a ļ¬nite state machine compiler with
output support for C, C++, Objective-C, D, Java
and Ruby source code.

         ā€¢ Mongrel HTTP parser
         ā€¢ Hpricot HTML/XML parser
         ā€¢ JSON parser
how Thin works
              thin 1.2.7 codename No Hup

# in lib/thin/connection.rb:42
# in Thin::Connection#receive_data


    process if @request.parse(data)


             # true: parsed, so process!
             # false: we need more data!
how Thin works
                 thin 1.2.7 codename No Hup

  # in lib/thin/connection.rb:52
  # in Thin::Connection#process

if threaded?
  @request.threaded = true
  EventMachine.defer(method( :pre_process),
                     method(:post_process))
else
  @request.threaded = false
  post_process(pre_process)
end
how EventMachine works
                  eventmachine 0.12.10

 # in lib/eventmachine.rb:1045
 # in EventMachine.defer
    unless @threadpool
      require ā€˜threadā€™
      @threadpool = []
      @threadqueue = ::Queue.new
      @resultqueue = ::Queue.new
      spawn_threadpool
    end
    @threadqueue << [op||blk,callback]
how Thin works
                   thin 1.2.7 codename No Hup

    # in lib/thin/connection.rb:68
    # in Thin::Connection#pre_process
@request.async_callback = method(:post_process)
# ...
response = AsyncResponse
catch(:async) do
  # Process the request calling the Rack adapter
  response = @app.call(@request.env)
end
response
how Thin works
              thin 1.2.7 codename No Hup

# in lib/thin/connection.rb:95
# in Thin::Connection#post_process
      @response.status,
      @response.headers,
      @response.body = *result
      # ...
      @response.each do |chunk|
        trace { chunk }
        send_data chunk
      end
Reactor Pattern
ā€¢ resources
ā€¢ synchronous event demultiplexer
ā€¢ dispatcher
ā€¢ request handler (Thin::Connection)


            by wikipedia
Table of Contents

ā€¢ how Thin works
ā€¢ how EventMachine works
ā€¢ how AMQP works
ā€¢ how Unicorn and Rainbows! works
how EventMachine works
          eventmachine 0.12.10
how EventMachine works
                    eventmachine 0.12.10
 # in lib/eventmachine.rb:571
 # in EventMachine.start_server
   s = if port
         start_tcp_server server, port
       else
         start_unix_server server
       end
   @acceptors[s] = [klass,args,block]
          #     s: server (in Reactor) uuid
          # klass: Thin::Connection
          # args: []
          # block: method(:initialize_connection)
how EventMachine works
                   eventmachine 0.12.10
 # in lib/eventmachine.rb:50
   case $eventmachine_library
     when :pure_ruby
       require ā€˜pr_eventmachineā€™
     when :extension
       require ā€˜rubyeventmachineā€™
     when :java
       require ā€˜jeventmachineā€™
how EventMachine works
                   eventmachine 0.12.10
 # in lib/pr_eventmachine.rb:318
 # in EventMachine.run
  loop {
    @current_loop_time = Time.now
    break if @stop_scheduled
    run_timers # timer event
    break if @stop_scheduled
    # epoll, kqueue, etc
    crank_selectables
    break if @stop_scheduled
    # close scheduling if client timeout
    run_heartbeats
how EventMachine works
                         eventmachine 0.12.10
       # in lib/eventmachine.rb:1445
       # in EventMachine.event_callback
elsif opcode == ConnectionData
  c = @conns[conn_binding] or raise ConnectionNotBound,
    ā€œreceived data #{data} for unknown signature:ā€ 
    ā€œ#{conn_binding}ā€
  c.receive_data data
elsif opcode == LoopbreakSignalled
                   #       opcode: event enum (int)
                   # conn_binding: connection uuid
                   #         data: received data
how Thin works
              thin 1.2.7 codename No Hup

# in lib/thin/connection.rb:42
# in Thin::Connection#receive_data


    process if @request.parse(data)


             # true: parsed, so process!
             # false: we need more data!
how EventMachine works
                          eventmachine 0.12.10
        # in lib/eventmachine.rb:1427
        # in EventMachine.event_callback
elsif opcode == ConnectionAccepted
  accep,args,blk = @acceptors[conn_binding]
  raise NoHandlerForAcceptedConnection unless accep
  c = accep.new data, *args
  @conns[data] = c
  blk and blk.call(c)
  c # (needed?)
elsif opcode == ConnectionCompleted
                    # conn_binding: server uuid
                    #         data: connection uuid
how Thin works
              thin 1.2.7 codename No Hup

# in lib/thin/backends/tcp_server.rb:16
# in Thin::TcpServer#connect

  EventMachine.start_server(
    @host, @port,
    Thin::Connection,
    &method(:initialize_connection))

         # rack app, backend ref, timeout, etc
how EventMachine works
                   eventmachine 0.12.10
 # in lib/pr_eventmachine.rb:256
      module EventMachine
        TimerFired            =   100
        ConnectionData        =   101
        ConnectionUnbound     =   102
        ConnectionAccepted    =   103
        ConnectionCompleted   =   104
        LoopbreakSignalled    =   105
      end
Table of Contents

ā€¢ how Thin works
ā€¢ how EventMachine works
ā€¢ how AMQP works
ā€¢ how Unicorn and Rainbows! works
how AMQP works

ā€¢ AMQP::BasicClient
 # extend to AMQP::Client
how AMQP works

ā€¢ AMQP::BasicClient
 # extend to AMQP::Client

ā€¢ AMQP::Client
 # included into EventMachine::Connection
how AMQP works
        amqp 0.6.7
how AMQP works
                      amqp 0.6.7

# in lib/amqp.rb:79
# in AMQP.start
    EM.run{
      @conn ||= connect *args
      @conn.callback(&blk) if blk
      @conn
    }
how AMQP works
                      amqp 0.6.7

# in lib/amqp.rb:18
# in AMQP.connect

         Client.connect *args
how AMQP works
                           amqp 0.6.7

    # in lib/amqp/client.rb:188
    # in AMQP::Client.connect
opts = AMQP.setting.merge(opts)
EM.connect opts[:host], opts[:port], self, opts
how Thin works
              thin 1.2.7 codename No Hup

# in lib/thin/backends/tcp_server.rb:16
# in Thin::TcpServer#connect

  EventMachine.start_server(
    @host, @port,
    Thin::Connection,
    &method(:initialize_connection))

         # rack app, backend ref, timeout, etc
how EventMachine works
                       eventmachine 0.12.10
     # in lib/eventmachine.rb:1571
     # in EventMachine.klass_from_handler
klass = if handler and handler.is_a?(Class)
  raise ArgumentError,
    ā€œmust provide module or #{klass.name}ā€ unless
    klass >= handler
  handler
elsif handler
  Class.new(klass){ include handle }
else
  klass   #   klass: EventMachine::Connection
end       # handler: Thin::Connection or AMQP::Client
how AMQP works
                      amqp 0.6.7

# in lib/amqp/client.rb:115
# in AMQP::Client#receive_data

   while frame = Frame.parse(@buf)
     log ā€™receiveā€™, frame
     process_frame frame
   end
how AMQP works

ā€¢ AMQP::Frame
 # basic building block of AMQP data stream
how AMQP works

ā€¢ AMQP::Frame
 # basic building block of AMQP data stream

ā€¢ AMQP::Buffer
 # frame buffer and parser
how AMQP works

ā€¢ AMQP::Frame
 # basic building block of AMQP data stream

ā€¢ AMQP::Buffer
 # frame buffer and parser

ā€¢ AMQP::Protocol::Connection
 # used in BasicClient#process_frame
how AMQP works

ā€¢ MQ
 # easy to use, high level wrapper
how AMQP works

ā€¢ MQ
 # easy to use, high level wrapper

ā€¢ MQ::Queue
 # the entities which receive messages
how AMQP works

ā€¢ MQ
 # easy to use, high level wrapper

ā€¢ MQ::Queue
 # the entities which receive messages

ā€¢ MQ::Exchange
 # the entities to which messages are sent
how AMQP works

ā€¢ MQ
 # easy to use, high level wrapper

ā€¢ MQ::Queue
 # the entities which receive messages

ā€¢ MQ::Exchange
 # the entities to which messages are sent


                 by wikipedia
how AMQP works
# default connection
MQ.new.queue(ā€˜nameā€™)

# default exchange (direct)
MQ.new.publish(ā€˜nameā€™)

#-- convenience wrapper (read: HACK)
#   for thread-local MQ object
MQ.queue(ā€˜nameā€™)
MQ.publish(ā€˜nameā€™)
how AMQP works
MQ.queues      # all created queues
MQ.exchanges   # all created exchanges
MQ.direct      # direct exchange
MQ.fanout      # fanout exchange
MQ.topic       #   topic exchange
MQ.headers     # headers exchange
Table of Contents

ā€¢ how Thin works
ā€¢ how EventMachine works
ā€¢ how AMQP works
ā€¢ how Unicorn and Rainbows! works
Unicorn? .
Unicorn? .
ā€¢ is not event-driven!
Unicorn? .
ā€¢ is not event-driven!
ā€¢ except Mongrel
  HTTP parser, all
  written in Ruby
Unicorn? .
ā€¢ is not event-driven!
ā€¢ except Mongrel
  HTTP parser, all
  written in Ruby

ā€¢ yet *super fast* for
  fast client
Unicorn? .
ā€¢ is not event-driven!
ā€¢ except Mongrel
  HTTP parser, all
  written in Ruby

ā€¢ yet *super fast* for
  fast client

ā€¢ preforking worker
  with blocking I/O
Unicorn? .               Rainbows!?
ā€¢ is not event-driven!
ā€¢ except Mongrel
  HTTP parser, all
  written in Ruby

ā€¢ yet *super fast* for
  fast client

ā€¢ preforking worker
  with blocking I/O
Unicorn? .               Rainbows!?
ā€¢ is not event-driven!   ā€¢ could be event-driven
ā€¢ except Mongrel
  HTTP parser, all
  written in Ruby

ā€¢ yet *super fast* for
  fast client

ā€¢ preforking worker
  with blocking I/O
Unicorn? .               Rainbows!?
ā€¢ is not event-driven!   ā€¢ could be event-driven
ā€¢ except Mongrel         ā€¢ also pure Ruby,
  HTTP parser, all         except...
  written in Ruby

ā€¢ yet *super fast* for
  fast client

ā€¢ preforking worker
  with blocking I/O
Unicorn? .               Rainbows!?
ā€¢ is not event-driven!   ā€¢ could be event-driven
ā€¢ except Mongrel         ā€¢ also pure Ruby,
  HTTP parser, all         except...
  written in Ruby

ā€¢ yet *super fast* for   ā€¢ *any* concurrency
  fast client              model

ā€¢ preforking worker
  with blocking I/O
Unicorn? .               Rainbows!?
ā€¢ is not event-driven!   ā€¢ could be event-driven
ā€¢ except Mongrel         ā€¢ also pure Ruby,
  HTTP parser, all         except...
  written in Ruby

ā€¢ yet *super fast* for   ā€¢ *any* concurrency
  fast client              model

ā€¢ preforking worker      ā€¢ provide network
  with blocking I/O        concurrency
Unicorn? .                  Rainbows!?
ā€¢ is not event-driven!
                         ā€¢ RevFiberSpawn
ā€¢ except Mongrel
  HTTP parser, all
  written in Ruby

ā€¢ yet *super fast* for
  fast client

ā€¢ preforking worker
  with blocking I/O
Unicorn? .                  Rainbows!?
ā€¢ is not event-driven!
                         ā€¢ RevFiberSpawn
ā€¢ except Mongrel
  HTTP parser, all       ā€¢ Revactor
  written in Ruby

ā€¢ yet *super fast* for
  fast client

ā€¢ preforking worker
  with blocking I/O
Unicorn? .                  Rainbows!?
ā€¢ is not event-driven!
                         ā€¢ RevFiberSpawn
ā€¢ except Mongrel
  HTTP parser, all       ā€¢ Revactor
  written in Ruby
                         ā€¢ ThreadPool
ā€¢ yet *super fast* for
  fast client

ā€¢ preforking worker
  with blocking I/O
Unicorn? .                  Rainbows!?
ā€¢ is not event-driven!
                         ā€¢ RevFiberSpawn
ā€¢ except Mongrel
  HTTP parser, all       ā€¢ Revactor
  written in Ruby
                         ā€¢ ThreadPool
ā€¢ yet *super fast* for   ā€¢ Rev
  fast client

ā€¢ preforking worker
  with blocking I/O
Unicorn? .                  Rainbows!?
ā€¢ is not event-driven!
                         ā€¢ RevFiberSpawn
ā€¢ except Mongrel
  HTTP parser, all       ā€¢ Revactor
  written in Ruby
                         ā€¢ ThreadPool
ā€¢ yet *super fast* for   ā€¢ Rev
  fast client

ā€¢ preforking worker      ā€¢ ThreadSpawn
  with blocking I/O
Unicorn? .                  Rainbows!?
ā€¢ is not event-driven!
                         ā€¢ RevFiberSpawn
ā€¢ except Mongrel
  HTTP parser, all       ā€¢ Revactor
  written in Ruby
                         ā€¢ ThreadPool
ā€¢ yet *super fast* for   ā€¢ Rev
  fast client

ā€¢ preforking worker      ā€¢ ThreadSpawn
  with blocking I/O
                         ā€¢ EventMachine
Unicorn? .                  Rainbows!?
ā€¢ is not event-driven!
                         ā€¢ RevFiberSpawn
ā€¢ except Mongrel                    ā€¢ RevThreadSpawn
  HTTP parser, all       ā€¢ Revactor
  written in Ruby
                         ā€¢ ThreadPool
ā€¢ yet *super fast* for   ā€¢ Rev
  fast client

ā€¢ preforking worker      ā€¢ ThreadSpawn
  with blocking I/O
                         ā€¢ EventMachine
Unicorn? .                  Rainbows!?
ā€¢ is not event-driven!
                         ā€¢ RevFiberSpawn
ā€¢ except Mongrel                    ā€¢ RevThreadSpawn
  HTTP parser, all       ā€¢ Revactor FiberSpawn
  written in Ruby                   ā€¢
                         ā€¢ ThreadPool
ā€¢ yet *super fast* for   ā€¢ Rev
  fast client

ā€¢ preforking worker      ā€¢ ThreadSpawn
  with blocking I/O
                         ā€¢ EventMachine
Unicorn? .                  Rainbows!?
ā€¢ is not event-driven!
                         ā€¢ RevFiberSpawn
ā€¢ except Mongrel                    ā€¢ RevThreadSpawn
  HTTP parser, all       ā€¢ Revactor FiberSpawn
  written in Ruby                   ā€¢
                         ā€¢ ThreadPool FiberPool
ā€¢ yet *super fast* for              ā€¢
  fast client            ā€¢ Rev
ā€¢ preforking worker      ā€¢ ThreadSpawn
  with blocking I/O
                         ā€¢ EventMachine
Unicorn? .                  Rainbows!?
ā€¢ is not event-driven!
                         ā€¢ RevFiberSpawn
ā€¢ except Mongrel                    ā€¢ RevThreadSpawn
  HTTP parser, all       ā€¢ Revactor FiberSpawn
  written in Ruby                   ā€¢
                         ā€¢ ThreadPool FiberPool
ā€¢ yet *super fast* for              ā€¢
  fast client            ā€¢ Rev
                                    ā€¢ NeverBlock
ā€¢ preforking worker      ā€¢ ThreadSpawn
  with blocking I/O
                         ā€¢ EventMachine
Unicorn? .                  Rainbows!?
ā€¢ is not event-driven!
                         ā€¢ RevFiberSpawn
ā€¢ except Mongrel                    ā€¢ RevThreadSpawn
  HTTP parser, all       ā€¢ Revactor FiberSpawn
  written in Ruby                   ā€¢
                         ā€¢ ThreadPool FiberPool
ā€¢ yet *super fast* for              ā€¢
  fast client            ā€¢ Rev
                                    ā€¢ NeverBlock
ā€¢ preforking worker      ā€¢ ThreadSpawn
  with blocking I/O                 ā€¢ RevThreadPool
                         ā€¢ EventMachine
Unicorn? .             Rainbows!?
unicorn master
_ unicorn worker[0]
| _ client[0]
_ unicorn worker[1]
| _ client[1]
_ unicorn worker[2]
| _ client[2]
...
_ unicorn worker[M]
    _ client[M]
Unicorn? .             Rainbows!?
unicorn master         rainbows! master
                        _ rainbows! worker[0]
_ unicorn worker[0]    | _ client[0,0]
| _ client[0]          | _ client[0,1]
                        | ...
_ unicorn worker[1]    | _ client[0,N]
| _ client[1]          _ rainbows! worker[1]
                        | _ client[1,0]
_ unicorn worker[2]    | ...
| _ client[2]          | _ client[1,N]
                        ...
...                     _ rainbows! worker[M]
_ unicorn worker[M]        _ client[M,0]
                            ...
    _ client[M]            _ client[M,N]
Unicorn? .             Rainbows!?
unicorn master         rainbows! master
                        _ rainbows! worker[0]
_ unicorn worker[0]    | _ client[0,0]------
                        | _ client[0,1]-------
                                                        ___app[0]
                                                       /___app[1]
| _ client[0]          | _ client[0,2]-------->--<
                        | ...                   __/
                                                              ...
                                                       `---app[P]
_ unicorn worker[1]    | _ client[0,N]----/
                        _ rainbows! worker[1]
| _ client[1]          | _ client[1,0]------
                        | _ client[1,1]-------
                                                        ___app[0]
                                                       /___app[1]
_ unicorn worker[2]    | _ client[1,2]-------->--<
                        | ...                   __/
                                                              ...
                                                       `---app[P]
| _ client[2]          | _ client[1,N]----/
                        _ rainbows! worker[M]
...                         _ client[M,0]------       ___app[0]
                            _ client[M,1]-------     /___app[1]
_ unicorn worker[M]        _ client[M,2]-------->--<        ...
                            ...                 __/    `---app[P]
    _ client[M]            _ client[M,N]----/
Unicorn? .              Rainbows!?
        static files
          |
    nginx |--> slow actions --> Rainbows!
          |
          `--> fast actions --> Unicorn
Unicorn? .
 http://unicorn.bogomips.org/
                                Rainbows!?
                                 http://rainbows.rubyforge.org/



             static files
               |
         nginx |--> slow actions --> Rainbows!
               |
               `--> fast actions --> Unicorn
how Unicorn works
         unicorn 0.97.0
how Unicorn works
                    unicorn 0.97.0

# in lib/unicorn.rb:270
# in Unicorn::HttpServer#start

         maintain_worker_count
how Unicorn works
                           unicorn 0.97.0

      # in lib/unicorn.rb:602
      # in Unicorn::HttpServer#maintain_worker_count
(off = WORKER.size - worker_process) == 0 and return
 off < 0 and return spawn_missing_workers
how Unicorn works
                           unicorn 0.97.0

      # in lib/unicorn.rb:591
      # in Unicorn::HttpServer#spawn_missing_workers
worker = Worker.new(worker_nr, Unicorn::Util.tmpio)
before_fork.call(self, worker)
WORKERS[fork {
  ready_pipe.close if ready_pipe
  self.ready_pipe = nil
  worker_loop(worker)
}] = worker
how Unicorn works
                     unicorn 0.97.0

# in lib/unicorn.rb:705
# in Unicorn::HttpServer#worker_loop

ready.each do |sock|
  begin
    process_client(sock.accept_nonblock)
    # workers load balancing here!! ^^
how Unicorn works
                          unicorn 0.97.0

     # in lib/unicorn.rb:630
     # in Unicorn::HttpServer#process_client
# read request, call app, write app response
def process_client(client)
  client.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
  response = app.call(env = REQUEST.read(client))
  # [...]
  HttpResponse.write(client, response,
    HttpRequest::PARSER.headers?)
how Unicorn works
                          unicorn 0.97.0

     # in lib/unicorn/http_request.rb:31
     # in Unicorn::HttpRequest#read

#   Does the majority of the IO processing.
#   It has been written in Ruby using about 8
#   different IO processing strategies.
#   [...]
#   Anyone who thinks they can make it faster is
#   more than welcome to take a crack at it.
how Rainbows! works
         rainbows 0.91.0
how Rainbows! works
              rainbows 0.91.0

Sorry! To be continued......
how Rainbows! works
              rainbows 0.91.0

Sorry! To be continued......


           ?

More Related Content

What's hot

Embedded Mirror Maker
Embedded Mirror MakerEmbedded Mirror Maker
Embedded Mirror Maker
Simon Suo
Ā 

What's hot (20)

Akka streams scala italy2015
Akka streams scala italy2015Akka streams scala italy2015
Akka streams scala italy2015
Ā 
Kubernetes #6 advanced scheduling
Kubernetes #6   advanced schedulingKubernetes #6   advanced scheduling
Kubernetes #6 advanced scheduling
Ā 
Akka streams
Akka streamsAkka streams
Akka streams
Ā 
Hadoop institutes in Bangalore
Hadoop institutes in BangaloreHadoop institutes in Bangalore
Hadoop institutes in Bangalore
Ā 
Apache Spark
Apache SparkApache Spark
Apache Spark
Ā 
Reactive mistakes - ScalaDays Chicago 2017
Reactive mistakes -  ScalaDays Chicago 2017Reactive mistakes -  ScalaDays Chicago 2017
Reactive mistakes - ScalaDays Chicago 2017
Ā 
Gude for C++11 in Apache Traffic Server
Gude for C++11 in Apache Traffic ServerGude for C++11 in Apache Traffic Server
Gude for C++11 in Apache Traffic Server
Ā 
How to manage large amounts of data with akka streams
How to manage large amounts of data with akka streamsHow to manage large amounts of data with akka streams
How to manage large amounts of data with akka streams
Ā 
Apache Storm
Apache StormApache Storm
Apache Storm
Ā 
S3, Cassandra or Outer Space? Dumping Time Series Data using Spark - Demi Ben...
S3, Cassandra or Outer Space? Dumping Time Series Data using Spark - Demi Ben...S3, Cassandra or Outer Space? Dumping Time Series Data using Spark - Demi Ben...
S3, Cassandra or Outer Space? Dumping Time Series Data using Spark - Demi Ben...
Ā 
A dive into akka streams: from the basics to a real-world scenario
A dive into akka streams: from the basics to a real-world scenarioA dive into akka streams: from the basics to a real-world scenario
A dive into akka streams: from the basics to a real-world scenario
Ā 
Universal metrics with Apache Beam
Universal metrics with Apache BeamUniversal metrics with Apache Beam
Universal metrics with Apache Beam
Ā 
Apache Airflow | What Is An Operator
Apache Airflow | What Is An OperatorApache Airflow | What Is An Operator
Apache Airflow | What Is An Operator
Ā 
Samza 0.13 meetup slide v1.0.pptx
Samza 0.13 meetup slide   v1.0.pptxSamza 0.13 meetup slide   v1.0.pptx
Samza 0.13 meetup slide v1.0.pptx
Ā 
Beam me up, Samza!
Beam me up, Samza!Beam me up, Samza!
Beam me up, Samza!
Ā 
Embedded Mirror Maker
Embedded Mirror MakerEmbedded Mirror Maker
Embedded Mirror Maker
Ā 
Reactive programming with Pivotal's reactor
Reactive programming with Pivotal's reactorReactive programming with Pivotal's reactor
Reactive programming with Pivotal's reactor
Ā 
Gearpump akka streams
Gearpump akka streamsGearpump akka streams
Gearpump akka streams
Ā 
Service discovery in mesos miguel, Angel Guillen
Service discovery in mesos miguel, Angel GuillenService discovery in mesos miguel, Angel Guillen
Service discovery in mesos miguel, Angel Guillen
Ā 
PSUG #52 Dataflow and simplified reactive programming with Akka-streams
PSUG #52 Dataflow and simplified reactive programming with Akka-streamsPSUG #52 Dataflow and simplified reactive programming with Akka-streams
PSUG #52 Dataflow and simplified reactive programming with Akka-streams
Ā 

Viewers also liked

2008-12-21 Rubinius
2008-12-21 Rubinius2008-12-21 Rubinius
2008-12-21 Rubinius
Lin Jen-Shin
Ā 
The Architecture of PicCollage Server
The Architecture of PicCollage ServerThe Architecture of PicCollage Server
The Architecture of PicCollage Server
Lin Jen-Shin
Ā 
2008-01-25 Tangible Value
2008-01-25 Tangible Value2008-01-25 Tangible Value
2008-01-25 Tangible Value
Lin Jen-Shin
Ā 
2012 05-08-lambda-draft
2012 05-08-lambda-draft2012 05-08-lambda-draft
2012 05-08-lambda-draft
Lin Jen-Shin
Ā 
Server Development Workflow For PicCollage
Server Development Workflow For PicCollageServer Development Workflow For PicCollage
Server Development Workflow For PicCollage
Lin Jen-Shin
Ā 
Concurrent Ruby Application Servers
Concurrent Ruby Application ServersConcurrent Ruby Application Servers
Concurrent Ruby Application Servers
Lin Jen-Shin
Ā 
2010 04-24-cerealize
2010 04-24-cerealize2010 04-24-cerealize
2010 04-24-cerealize
Lin Jen-Shin
Ā 
2007-06-24 The Lost Piece
2007-06-24 The Lost Piece2007-06-24 The Lost Piece
2007-06-24 The Lost Piece
Lin Jen-Shin
Ā 

Viewers also liked (8)

2008-12-21 Rubinius
2008-12-21 Rubinius2008-12-21 Rubinius
2008-12-21 Rubinius
Ā 
The Architecture of PicCollage Server
The Architecture of PicCollage ServerThe Architecture of PicCollage Server
The Architecture of PicCollage Server
Ā 
2008-01-25 Tangible Value
2008-01-25 Tangible Value2008-01-25 Tangible Value
2008-01-25 Tangible Value
Ā 
2012 05-08-lambda-draft
2012 05-08-lambda-draft2012 05-08-lambda-draft
2012 05-08-lambda-draft
Ā 
Server Development Workflow For PicCollage
Server Development Workflow For PicCollageServer Development Workflow For PicCollage
Server Development Workflow For PicCollage
Ā 
Concurrent Ruby Application Servers
Concurrent Ruby Application ServersConcurrent Ruby Application Servers
Concurrent Ruby Application Servers
Ā 
2010 04-24-cerealize
2010 04-24-cerealize2010 04-24-cerealize
2010 04-24-cerealize
Ā 
2007-06-24 The Lost Piece
2007-06-24 The Lost Piece2007-06-24 The Lost Piece
2007-06-24 The Lost Piece
Ā 

Similar to 2010-04-13 Reactor Pattern & Event Driven Programming 2

Use perl creating web services with xml rpc
Use perl creating web services with xml rpcUse perl creating web services with xml rpc
Use perl creating web services with xml rpc
Johnny Pork
Ā 

Similar to 2010-04-13 Reactor Pattern & Event Driven Programming 2 (20)

TorqueBox - Ruby Hoedown 2011
TorqueBox - Ruby Hoedown 2011TorqueBox - Ruby Hoedown 2011
TorqueBox - Ruby Hoedown 2011
Ā 
Asynchronous Architectures for Implementing Scalable Cloud Services - Evan Co...
Asynchronous Architectures for Implementing Scalable Cloud Services - Evan Co...Asynchronous Architectures for Implementing Scalable Cloud Services - Evan Co...
Asynchronous Architectures for Implementing Scalable Cloud Services - Evan Co...
Ā 
Training Slides: 153 - Working with the CLI
Training Slides: 153 - Working with the CLITraining Slides: 153 - Working with the CLI
Training Slides: 153 - Working with the CLI
Ā 
Nike tech talk.2
Nike tech talk.2Nike tech talk.2
Nike tech talk.2
Ā 
TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011
Ā 
SnappyData overview NikeTechTalk 11/19/15
SnappyData overview NikeTechTalk 11/19/15SnappyData overview NikeTechTalk 11/19/15
SnappyData overview NikeTechTalk 11/19/15
Ā 
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
Ā 
XS Japan 2008 Xen Mgmt English
XS Japan 2008 Xen Mgmt EnglishXS Japan 2008 Xen Mgmt English
XS Japan 2008 Xen Mgmt English
Ā 
DevoxxUK: Optimizating Application Performance on Kubernetes
DevoxxUK: Optimizating Application Performance on KubernetesDevoxxUK: Optimizating Application Performance on Kubernetes
DevoxxUK: Optimizating Application Performance on Kubernetes
Ā 
.NET Architects Day - DNAD 2011
.NET Architects Day - DNAD 2011.NET Architects Day - DNAD 2011
.NET Architects Day - DNAD 2011
Ā 
09 - FƔbio Akita - AlƩm do rails
09 - FƔbio Akita - AlƩm do rails09 - FƔbio Akita - AlƩm do rails
09 - FƔbio Akita - AlƩm do rails
Ā 
Building Web APIs that Scale
Building Web APIs that ScaleBuilding Web APIs that Scale
Building Web APIs that Scale
Ā 
Deploying Apache Flume to enable low-latency analytics
Deploying Apache Flume to enable low-latency analyticsDeploying Apache Flume to enable low-latency analytics
Deploying Apache Flume to enable low-latency analytics
Ā 
Container orchestration from theory to practice
Container orchestration from theory to practiceContainer orchestration from theory to practice
Container orchestration from theory to practice
Ā 
Introduction to Marionette Collective
Introduction to Marionette CollectiveIntroduction to Marionette Collective
Introduction to Marionette Collective
Ā 
Rack
RackRack
Rack
Ā 
Evented Ruby VS Node.js
Evented Ruby VS Node.jsEvented Ruby VS Node.js
Evented Ruby VS Node.js
Ā 
Velocity 2010 - ATS
Velocity 2010 - ATSVelocity 2010 - ATS
Velocity 2010 - ATS
Ā 
Spark on Yarn
Spark on YarnSpark on Yarn
Spark on Yarn
Ā 
Use perl creating web services with xml rpc
Use perl creating web services with xml rpcUse perl creating web services with xml rpc
Use perl creating web services with xml rpc
Ā 

Recently uploaded

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
Ā 
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
Enterprise Knowledge
Ā 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
Ā 

Recently uploaded (20)

Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
Ā 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
Ā 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
Ā 
šŸ¬ The future of MySQL is Postgres šŸ˜
šŸ¬  The future of MySQL is Postgres   šŸ˜šŸ¬  The future of MySQL is Postgres   šŸ˜
šŸ¬ The future of MySQL is Postgres šŸ˜
Ā 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
Ā 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
Ā 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
Ā 
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
Ā 
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
Ā 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
Ā 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
Ā 
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
Ā 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
Ā 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
Ā 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
Ā 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
Ā 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
Ā 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Ā 
Finology Group ā€“ Insurtech Innovation Award 2024
Finology Group ā€“ Insurtech Innovation Award 2024Finology Group ā€“ Insurtech Innovation Award 2024
Finology Group ā€“ Insurtech Innovation Award 2024
Ā 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
Ā 

2010-04-13 Reactor Pattern & Event Driven Programming 2

  • 1. Reactor Pattern & Event-Driven Programming A scalable concurrent approach, using EventMachine with Thin as an example Lin Jen-Shin, http://godfat.org/
  • 2. Reactor Pattern & Event-Driven Programming A scalable concurrent approach, using EventMachine with Thin as an example Lin Jen-Shin, http://godfat.org/
  • 3. Reactor Pattern & Event-Driven Programming http://godfat.org/slide/2010-04-13-reactor-pattern-and-2.pdf Lin Jen-Shin, http://godfat.org/
  • 4. Table of Contents ā€¢ concurrency, why and how in network ā€¢ Event-Driven Programming explained in Flash with Ruby syntax ā€¢ Reactor Pattern in EventMachine with Thin ā€¢ how Thin works ā€¢ how EventMachine works
  • 5. Event-Driven Programming register method(:do_something) loop{ loop{ # you control the flow # event loop control the flow, do_something # later it calls your callback } event = pop_event_queue dispatch event if event }
  • 6. Reactor Pattern register method(:handle) loop{ loop{ data = read data = partial_read handle data event = process data } dispatch event if event }
  • 7. Table of Contents ā€¢ how Thin works ā€¢ how EventMachine works
  • 8. Table of Contents ā€¢ how Thin works ā€¢ how EventMachine works
  • 9. Table of Contents ā€¢ how Thin works ā€¢ how EventMachine works ā€¢ how AMQP works
  • 10. Table of Contents ā€¢ how Thin works ā€¢ how EventMachine works ā€¢ how AMQP works ā€¢ how Unicorn and Rainbows! works
  • 12. Reactor Pattern EventMachine Request (demultiplexer (resource) + dispatcher)
  • 13. Reactor Pattern EventMachine Request Thin (or AMQP) (demultiplexer (resource) (request handler) + dispatcher)
  • 14. Reactor Pattern EventMachine Request Thin (or AMQP) (demultiplexer (resource) (request handler) + dispatcher) Rack Thin handler
  • 15. Reactor Pattern EventMachine Request Thin (or AMQP) (demultiplexer (resource) (request handler) + dispatcher) Rack Rails Rack Thin rack env adapter handler
  • 16. Reactor Pattern EventMachine Request Thin (or AMQP) (demultiplexer (resource) (request handler) + dispatcher) Rack Rails Rack Thin Rails rack env adapter handler
  • 17. your rails application Reactor Pattern EventMachine Request Thin (or AMQP) (demultiplexer (resource) (request handler) + dispatcher) Rack Rails Rack Thin Rails rack env adapter handler
  • 18. how Thin works Thin (or AMQP) (request handler)
  • 19. how Thin works ā€¢ Thin::Server
  • 20. how Thin works ā€¢ Thin::Server ā€¢ Thin::Backends::TcpServer # communicate with EventMachine
  • 21. how Thin works ā€¢ Thin::Server ā€¢ Thin::Backends::TcpServer # communicate with EventMachine ā€¢ Thin::Connection # EventMachine event handler
  • 22. how Thin works ā€¢ Thin::Server ā€¢ Thin::Backends::TcpServer # communicate with EventMachine ā€¢ Thin::Connection # EventMachine event handler ā€¢ Thin::Request # partial HTTP request parsing # Rack env builder
  • 24. how Thin works Thin::Server Backends::TcpServer
  • 25. how Thin works Thin::Server Backends::TcpServer Connection
  • 26. how Thin works Thin::Server Backends::TcpServer Connection Request
  • 27. how Thin works Thin::Server Backends::TcpServer Connection Connection Request Request
  • 28. how Thin works Thin::Server Backends::TcpServer Connection Connection Connection Request Request Request
  • 29. how Thin works thin 1.2.7 codename No Hup
  • 30. how Thin works thin 1.2.7 codename No Hup # in lib/thin/backends/tcp_server.rb:16 # in Thin::TcpServer#connect EventMachine.start_server( @host, @port, Thin::Connection, &method(:initialize_connection)) # rack app, backend ref, timeout, etc
  • 31. how Thin works thin 1.2.7 codename No Hup # in lib/thin/connection.rb:42 # in Thin::Connection#receive_data process if @request.parse(data) # true: parsed, so process! # false: we need more data!
  • 32. how Thin works thin 1.2.7 codename No Hup # in lib/thin/request.rb:82 # in Thin::Request#parse @request = @parser.execute(@env, @data, @nparsed) # @env: Rack env # @data: HTTP header buffer # @nparsed: index of parsed data
  • 33. how Thin works thin 1.2.7 codename No Hup // in ext/thin_parser/thin.c:335 // in thin.c#Thin_HttpParser_execute thin_http_parser_execute(http, dptr, dlen, from); // http: HTTP parser pointer // dptr: HTTP header data pointer // dlen: HTTP header data length // form: previous @nparsed
  • 34. how Thin works thin 1.2.7 codename No Hup // in ext/thin_parser/parser.rl:102 // in parser.rl#thin_http_parser_execute // (itā€™s mongrelā€™s http parser) size_t thin_http_parser_execute( http_parser *parser, const char *buffer, size_t len, size_t off)
  • 35. how Thin works thin 1.2.7 codename No Hup Ragel is a ļ¬nite state machine compiler with output support for C, C++, Objective-C, D, Java and Ruby source code.
  • 36. how Thin works thin 1.2.7 codename No Hup Ragel is a ļ¬nite state machine compiler with output support for C, C++, Objective-C, D, Java and Ruby source code. ā€¢ Mongrel HTTP parser ā€¢ Hpricot HTML/XML parser ā€¢ JSON parser
  • 37. how Thin works thin 1.2.7 codename No Hup # in lib/thin/connection.rb:42 # in Thin::Connection#receive_data process if @request.parse(data) # true: parsed, so process! # false: we need more data!
  • 38. how Thin works thin 1.2.7 codename No Hup # in lib/thin/connection.rb:52 # in Thin::Connection#process if threaded? @request.threaded = true EventMachine.defer(method( :pre_process), method(:post_process)) else @request.threaded = false post_process(pre_process) end
  • 39. how EventMachine works eventmachine 0.12.10 # in lib/eventmachine.rb:1045 # in EventMachine.defer unless @threadpool require ā€˜threadā€™ @threadpool = [] @threadqueue = ::Queue.new @resultqueue = ::Queue.new spawn_threadpool end @threadqueue << [op||blk,callback]
  • 40. how Thin works thin 1.2.7 codename No Hup # in lib/thin/connection.rb:68 # in Thin::Connection#pre_process @request.async_callback = method(:post_process) # ... response = AsyncResponse catch(:async) do # Process the request calling the Rack adapter response = @app.call(@request.env) end response
  • 41. how Thin works thin 1.2.7 codename No Hup # in lib/thin/connection.rb:95 # in Thin::Connection#post_process @response.status, @response.headers, @response.body = *result # ... @response.each do |chunk| trace { chunk } send_data chunk end
  • 42. Reactor Pattern ā€¢ resources ā€¢ synchronous event demultiplexer ā€¢ dispatcher ā€¢ request handler (Thin::Connection) by wikipedia
  • 43. Table of Contents ā€¢ how Thin works ā€¢ how EventMachine works ā€¢ how AMQP works ā€¢ how Unicorn and Rainbows! works
  • 44. how EventMachine works eventmachine 0.12.10
  • 45. how EventMachine works eventmachine 0.12.10 # in lib/eventmachine.rb:571 # in EventMachine.start_server s = if port start_tcp_server server, port else start_unix_server server end @acceptors[s] = [klass,args,block] # s: server (in Reactor) uuid # klass: Thin::Connection # args: [] # block: method(:initialize_connection)
  • 46. how EventMachine works eventmachine 0.12.10 # in lib/eventmachine.rb:50 case $eventmachine_library when :pure_ruby require ā€˜pr_eventmachineā€™ when :extension require ā€˜rubyeventmachineā€™ when :java require ā€˜jeventmachineā€™
  • 47. how EventMachine works eventmachine 0.12.10 # in lib/pr_eventmachine.rb:318 # in EventMachine.run loop { @current_loop_time = Time.now break if @stop_scheduled run_timers # timer event break if @stop_scheduled # epoll, kqueue, etc crank_selectables break if @stop_scheduled # close scheduling if client timeout run_heartbeats
  • 48. how EventMachine works eventmachine 0.12.10 # in lib/eventmachine.rb:1445 # in EventMachine.event_callback elsif opcode == ConnectionData c = @conns[conn_binding] or raise ConnectionNotBound, ā€œreceived data #{data} for unknown signature:ā€ ā€œ#{conn_binding}ā€ c.receive_data data elsif opcode == LoopbreakSignalled # opcode: event enum (int) # conn_binding: connection uuid # data: received data
  • 49. how Thin works thin 1.2.7 codename No Hup # in lib/thin/connection.rb:42 # in Thin::Connection#receive_data process if @request.parse(data) # true: parsed, so process! # false: we need more data!
  • 50. how EventMachine works eventmachine 0.12.10 # in lib/eventmachine.rb:1427 # in EventMachine.event_callback elsif opcode == ConnectionAccepted accep,args,blk = @acceptors[conn_binding] raise NoHandlerForAcceptedConnection unless accep c = accep.new data, *args @conns[data] = c blk and blk.call(c) c # (needed?) elsif opcode == ConnectionCompleted # conn_binding: server uuid # data: connection uuid
  • 51. how Thin works thin 1.2.7 codename No Hup # in lib/thin/backends/tcp_server.rb:16 # in Thin::TcpServer#connect EventMachine.start_server( @host, @port, Thin::Connection, &method(:initialize_connection)) # rack app, backend ref, timeout, etc
  • 52. how EventMachine works eventmachine 0.12.10 # in lib/pr_eventmachine.rb:256 module EventMachine TimerFired = 100 ConnectionData = 101 ConnectionUnbound = 102 ConnectionAccepted = 103 ConnectionCompleted = 104 LoopbreakSignalled = 105 end
  • 53. Table of Contents ā€¢ how Thin works ā€¢ how EventMachine works ā€¢ how AMQP works ā€¢ how Unicorn and Rainbows! works
  • 54. how AMQP works ā€¢ AMQP::BasicClient # extend to AMQP::Client
  • 55. how AMQP works ā€¢ AMQP::BasicClient # extend to AMQP::Client ā€¢ AMQP::Client # included into EventMachine::Connection
  • 56. how AMQP works amqp 0.6.7
  • 57. how AMQP works amqp 0.6.7 # in lib/amqp.rb:79 # in AMQP.start EM.run{ @conn ||= connect *args @conn.callback(&blk) if blk @conn }
  • 58. how AMQP works amqp 0.6.7 # in lib/amqp.rb:18 # in AMQP.connect Client.connect *args
  • 59. how AMQP works amqp 0.6.7 # in lib/amqp/client.rb:188 # in AMQP::Client.connect opts = AMQP.setting.merge(opts) EM.connect opts[:host], opts[:port], self, opts
  • 60. how Thin works thin 1.2.7 codename No Hup # in lib/thin/backends/tcp_server.rb:16 # in Thin::TcpServer#connect EventMachine.start_server( @host, @port, Thin::Connection, &method(:initialize_connection)) # rack app, backend ref, timeout, etc
  • 61. how EventMachine works eventmachine 0.12.10 # in lib/eventmachine.rb:1571 # in EventMachine.klass_from_handler klass = if handler and handler.is_a?(Class) raise ArgumentError, ā€œmust provide module or #{klass.name}ā€ unless klass >= handler handler elsif handler Class.new(klass){ include handle } else klass # klass: EventMachine::Connection end # handler: Thin::Connection or AMQP::Client
  • 62. how AMQP works amqp 0.6.7 # in lib/amqp/client.rb:115 # in AMQP::Client#receive_data while frame = Frame.parse(@buf) log ā€™receiveā€™, frame process_frame frame end
  • 63. how AMQP works ā€¢ AMQP::Frame # basic building block of AMQP data stream
  • 64. how AMQP works ā€¢ AMQP::Frame # basic building block of AMQP data stream ā€¢ AMQP::Buffer # frame buffer and parser
  • 65. how AMQP works ā€¢ AMQP::Frame # basic building block of AMQP data stream ā€¢ AMQP::Buffer # frame buffer and parser ā€¢ AMQP::Protocol::Connection # used in BasicClient#process_frame
  • 66. how AMQP works ā€¢ MQ # easy to use, high level wrapper
  • 67. how AMQP works ā€¢ MQ # easy to use, high level wrapper ā€¢ MQ::Queue # the entities which receive messages
  • 68. how AMQP works ā€¢ MQ # easy to use, high level wrapper ā€¢ MQ::Queue # the entities which receive messages ā€¢ MQ::Exchange # the entities to which messages are sent
  • 69. how AMQP works ā€¢ MQ # easy to use, high level wrapper ā€¢ MQ::Queue # the entities which receive messages ā€¢ MQ::Exchange # the entities to which messages are sent by wikipedia
  • 70. how AMQP works # default connection MQ.new.queue(ā€˜nameā€™) # default exchange (direct) MQ.new.publish(ā€˜nameā€™) #-- convenience wrapper (read: HACK) # for thread-local MQ object MQ.queue(ā€˜nameā€™) MQ.publish(ā€˜nameā€™)
  • 71. how AMQP works MQ.queues # all created queues MQ.exchanges # all created exchanges MQ.direct # direct exchange MQ.fanout # fanout exchange MQ.topic # topic exchange MQ.headers # headers exchange
  • 72. Table of Contents ā€¢ how Thin works ā€¢ how EventMachine works ā€¢ how AMQP works ā€¢ how Unicorn and Rainbows! works
  • 74. Unicorn? . ā€¢ is not event-driven!
  • 75. Unicorn? . ā€¢ is not event-driven! ā€¢ except Mongrel HTTP parser, all written in Ruby
  • 76. Unicorn? . ā€¢ is not event-driven! ā€¢ except Mongrel HTTP parser, all written in Ruby ā€¢ yet *super fast* for fast client
  • 77. Unicorn? . ā€¢ is not event-driven! ā€¢ except Mongrel HTTP parser, all written in Ruby ā€¢ yet *super fast* for fast client ā€¢ preforking worker with blocking I/O
  • 78. Unicorn? . Rainbows!? ā€¢ is not event-driven! ā€¢ except Mongrel HTTP parser, all written in Ruby ā€¢ yet *super fast* for fast client ā€¢ preforking worker with blocking I/O
  • 79. Unicorn? . Rainbows!? ā€¢ is not event-driven! ā€¢ could be event-driven ā€¢ except Mongrel HTTP parser, all written in Ruby ā€¢ yet *super fast* for fast client ā€¢ preforking worker with blocking I/O
  • 80. Unicorn? . Rainbows!? ā€¢ is not event-driven! ā€¢ could be event-driven ā€¢ except Mongrel ā€¢ also pure Ruby, HTTP parser, all except... written in Ruby ā€¢ yet *super fast* for fast client ā€¢ preforking worker with blocking I/O
  • 81. Unicorn? . Rainbows!? ā€¢ is not event-driven! ā€¢ could be event-driven ā€¢ except Mongrel ā€¢ also pure Ruby, HTTP parser, all except... written in Ruby ā€¢ yet *super fast* for ā€¢ *any* concurrency fast client model ā€¢ preforking worker with blocking I/O
  • 82. Unicorn? . Rainbows!? ā€¢ is not event-driven! ā€¢ could be event-driven ā€¢ except Mongrel ā€¢ also pure Ruby, HTTP parser, all except... written in Ruby ā€¢ yet *super fast* for ā€¢ *any* concurrency fast client model ā€¢ preforking worker ā€¢ provide network with blocking I/O concurrency
  • 83. Unicorn? . Rainbows!? ā€¢ is not event-driven! ā€¢ RevFiberSpawn ā€¢ except Mongrel HTTP parser, all written in Ruby ā€¢ yet *super fast* for fast client ā€¢ preforking worker with blocking I/O
  • 84. Unicorn? . Rainbows!? ā€¢ is not event-driven! ā€¢ RevFiberSpawn ā€¢ except Mongrel HTTP parser, all ā€¢ Revactor written in Ruby ā€¢ yet *super fast* for fast client ā€¢ preforking worker with blocking I/O
  • 85. Unicorn? . Rainbows!? ā€¢ is not event-driven! ā€¢ RevFiberSpawn ā€¢ except Mongrel HTTP parser, all ā€¢ Revactor written in Ruby ā€¢ ThreadPool ā€¢ yet *super fast* for fast client ā€¢ preforking worker with blocking I/O
  • 86. Unicorn? . Rainbows!? ā€¢ is not event-driven! ā€¢ RevFiberSpawn ā€¢ except Mongrel HTTP parser, all ā€¢ Revactor written in Ruby ā€¢ ThreadPool ā€¢ yet *super fast* for ā€¢ Rev fast client ā€¢ preforking worker with blocking I/O
  • 87. Unicorn? . Rainbows!? ā€¢ is not event-driven! ā€¢ RevFiberSpawn ā€¢ except Mongrel HTTP parser, all ā€¢ Revactor written in Ruby ā€¢ ThreadPool ā€¢ yet *super fast* for ā€¢ Rev fast client ā€¢ preforking worker ā€¢ ThreadSpawn with blocking I/O
  • 88. Unicorn? . Rainbows!? ā€¢ is not event-driven! ā€¢ RevFiberSpawn ā€¢ except Mongrel HTTP parser, all ā€¢ Revactor written in Ruby ā€¢ ThreadPool ā€¢ yet *super fast* for ā€¢ Rev fast client ā€¢ preforking worker ā€¢ ThreadSpawn with blocking I/O ā€¢ EventMachine
  • 89. Unicorn? . Rainbows!? ā€¢ is not event-driven! ā€¢ RevFiberSpawn ā€¢ except Mongrel ā€¢ RevThreadSpawn HTTP parser, all ā€¢ Revactor written in Ruby ā€¢ ThreadPool ā€¢ yet *super fast* for ā€¢ Rev fast client ā€¢ preforking worker ā€¢ ThreadSpawn with blocking I/O ā€¢ EventMachine
  • 90. Unicorn? . Rainbows!? ā€¢ is not event-driven! ā€¢ RevFiberSpawn ā€¢ except Mongrel ā€¢ RevThreadSpawn HTTP parser, all ā€¢ Revactor FiberSpawn written in Ruby ā€¢ ā€¢ ThreadPool ā€¢ yet *super fast* for ā€¢ Rev fast client ā€¢ preforking worker ā€¢ ThreadSpawn with blocking I/O ā€¢ EventMachine
  • 91. Unicorn? . Rainbows!? ā€¢ is not event-driven! ā€¢ RevFiberSpawn ā€¢ except Mongrel ā€¢ RevThreadSpawn HTTP parser, all ā€¢ Revactor FiberSpawn written in Ruby ā€¢ ā€¢ ThreadPool FiberPool ā€¢ yet *super fast* for ā€¢ fast client ā€¢ Rev ā€¢ preforking worker ā€¢ ThreadSpawn with blocking I/O ā€¢ EventMachine
  • 92. Unicorn? . Rainbows!? ā€¢ is not event-driven! ā€¢ RevFiberSpawn ā€¢ except Mongrel ā€¢ RevThreadSpawn HTTP parser, all ā€¢ Revactor FiberSpawn written in Ruby ā€¢ ā€¢ ThreadPool FiberPool ā€¢ yet *super fast* for ā€¢ fast client ā€¢ Rev ā€¢ NeverBlock ā€¢ preforking worker ā€¢ ThreadSpawn with blocking I/O ā€¢ EventMachine
  • 93. Unicorn? . Rainbows!? ā€¢ is not event-driven! ā€¢ RevFiberSpawn ā€¢ except Mongrel ā€¢ RevThreadSpawn HTTP parser, all ā€¢ Revactor FiberSpawn written in Ruby ā€¢ ā€¢ ThreadPool FiberPool ā€¢ yet *super fast* for ā€¢ fast client ā€¢ Rev ā€¢ NeverBlock ā€¢ preforking worker ā€¢ ThreadSpawn with blocking I/O ā€¢ RevThreadPool ā€¢ EventMachine
  • 94. Unicorn? . Rainbows!? unicorn master _ unicorn worker[0] | _ client[0] _ unicorn worker[1] | _ client[1] _ unicorn worker[2] | _ client[2] ... _ unicorn worker[M] _ client[M]
  • 95. Unicorn? . Rainbows!? unicorn master rainbows! master _ rainbows! worker[0] _ unicorn worker[0] | _ client[0,0] | _ client[0] | _ client[0,1] | ... _ unicorn worker[1] | _ client[0,N] | _ client[1] _ rainbows! worker[1] | _ client[1,0] _ unicorn worker[2] | ... | _ client[2] | _ client[1,N] ... ... _ rainbows! worker[M] _ unicorn worker[M] _ client[M,0] ... _ client[M] _ client[M,N]
  • 96. Unicorn? . Rainbows!? unicorn master rainbows! master _ rainbows! worker[0] _ unicorn worker[0] | _ client[0,0]------ | _ client[0,1]------- ___app[0] /___app[1] | _ client[0] | _ client[0,2]-------->--< | ... __/ ... `---app[P] _ unicorn worker[1] | _ client[0,N]----/ _ rainbows! worker[1] | _ client[1] | _ client[1,0]------ | _ client[1,1]------- ___app[0] /___app[1] _ unicorn worker[2] | _ client[1,2]-------->--< | ... __/ ... `---app[P] | _ client[2] | _ client[1,N]----/ _ rainbows! worker[M] ... _ client[M,0]------ ___app[0] _ client[M,1]------- /___app[1] _ unicorn worker[M] _ client[M,2]-------->--< ... ... __/ `---app[P] _ client[M] _ client[M,N]----/
  • 97. Unicorn? . Rainbows!? static files | nginx |--> slow actions --> Rainbows! | `--> fast actions --> Unicorn
  • 98. Unicorn? . http://unicorn.bogomips.org/ Rainbows!? http://rainbows.rubyforge.org/ static files | nginx |--> slow actions --> Rainbows! | `--> fast actions --> Unicorn
  • 99. how Unicorn works unicorn 0.97.0
  • 100. how Unicorn works unicorn 0.97.0 # in lib/unicorn.rb:270 # in Unicorn::HttpServer#start maintain_worker_count
  • 101. how Unicorn works unicorn 0.97.0 # in lib/unicorn.rb:602 # in Unicorn::HttpServer#maintain_worker_count (off = WORKER.size - worker_process) == 0 and return off < 0 and return spawn_missing_workers
  • 102. how Unicorn works unicorn 0.97.0 # in lib/unicorn.rb:591 # in Unicorn::HttpServer#spawn_missing_workers worker = Worker.new(worker_nr, Unicorn::Util.tmpio) before_fork.call(self, worker) WORKERS[fork { ready_pipe.close if ready_pipe self.ready_pipe = nil worker_loop(worker) }] = worker
  • 103. how Unicorn works unicorn 0.97.0 # in lib/unicorn.rb:705 # in Unicorn::HttpServer#worker_loop ready.each do |sock| begin process_client(sock.accept_nonblock) # workers load balancing here!! ^^
  • 104. how Unicorn works unicorn 0.97.0 # in lib/unicorn.rb:630 # in Unicorn::HttpServer#process_client # read request, call app, write app response def process_client(client) client.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) response = app.call(env = REQUEST.read(client)) # [...] HttpResponse.write(client, response, HttpRequest::PARSER.headers?)
  • 105. how Unicorn works unicorn 0.97.0 # in lib/unicorn/http_request.rb:31 # in Unicorn::HttpRequest#read # Does the majority of the IO processing. # It has been written in Ruby using about 8 # different IO processing strategies. # [...] # Anyone who thinks they can make it faster is # more than welcome to take a crack at it.
  • 106. how Rainbows! works rainbows 0.91.0
  • 107. how Rainbows! works rainbows 0.91.0 Sorry! To be continued......
  • 108. how Rainbows! works rainbows 0.91.0 Sorry! To be continued...... ?