SlideShare a Scribd company logo
1 of 43
Download to read offline
0-60 with Goliath
                    Building high performance (Ruby) web-services


                                                     Ilya Grigorik
                                                        @igrigorik


0-60 with Goliath                  @igrigorik
-   “Social Analytics”              - Goliath == v3 API stack
                    -   Rails frontend                  - Open sourced in 2011
                    -   Ruby backend                    - Growing community
                    -   95%+ of traffic via API’s




                                    +                     +


                                                               Brief History
                                                              Goliath @ PostRank


0-60 with Goliath                          @igrigorik
Rails
                                              HTTP API               …

                                   HTTP API               HTTP API         HTTP API
                SQL

                                     SQL
                                      SQL                  SQL
                                                            SQL               …
                                       SQL                   Solr



      • Separate logical & physical services
      • Easy to tune, easy to maintain, easy to “scale”              PRO
      • Stable code, fault-tolerance


                                 • Higher upfront ops cost
                    CON          • Lots of cross-service communication


0-60 with Goliath                            @igrigorik
0-60 with Goliath   @igrigorik
www.goliath.io




     • Single responsibility web-services

     • Async HTTP response streaming + progressive notifications
     • Async HTTP request streaming + progressive notifications

     • Multiple requests within the same VM              … lower ops costs

     • Keep-alive support
                                                         … full HTTP 1.1 support
     • Pipelining support

     • Ruby API & “X-Ruby friendly”                      … Ruby polyglot!
     • Easy to maintain & test


0-60 with Goliath                           @igrigorik
HTTP Pipelining + Keep-Alive 101
                                     perhaps not as simple as it may seem…




0-60 with Goliath              @igrigorik
conn = EM::HttpRequest.new('http://oredev.org')

r1 = conn.get :path => ”2011/speakers", :keepalive => true # 250 ms
r2 = conn.get :path => ”2011/faq"                  # 300 ms

# wait until done …


      Total execution time is:                                Answer:
      (a) 250 ms            ~ 65% truthiness
      (b) 300 ms            ~ 25% truthiness *                All of the above!
      (c) 550 ms            ~ 10% truthiness **



                                                                      HTTP Quiz
                                                         this is not a trick question…


0-60 with Goliath                           @igrigorik
Client                   Server


                                         20 ms
                                                              TCP handshake

                                                              HTTP Request
                                               40 ms          • headers, body
                                             processing
                                                              Multi-part body (*)

                                                              Terminate connection
            + 40ms TCP setup (network)
            + 20ms request (network)
            + 40ms processing
            + 20ms response (network)                                   HTTP 1.0
              66% of time in network overhead                        RFC 1945 (1996)


0-60 with Goliath                                @igrigorik
Research done at Google shows that an increase
            from 5Mbps to 10Mbps results in a disappointing
            5% improvement in page load times.

            Or put slightly differently, a 10Mbps connection,
            on average uses only 16% of its capacity.



                                               http://bit.ly/oemX0I



0-60 with Goliath                 @igrigorik
Keep-alive
                                 • Re-use open connection
                                 • No multiplexing, serial
                                 • Default to “on”



                                 Pipelining
                                 • No multiplexing
                                 • Parallel requests




                                                 HTTP 1.1
                                              RFC 2616 (1999)


0-60 with Goliath   @igrigorik
+ 40ms TCP setup (network)

                    + 20ms request (network)
                    + 40ms processing
                    + 20ms response (network)

                    x 40ms TCP setup (network)

                    + 20ms request (network)
                    + 40ms processing
                    + 20ms response (network)

                    200ms for two requests

                    Small win over HTTP 1.0

                                                 Keep-alive
                                                 RFC 2616 (1999)


0-60 with Goliath         @igrigorik
Net:HTTP




          Connection: close < ugh!
                                                       Keep-alive
                                                       RFC 2616 (1999)


0-60 with Goliath                    @igrigorik
+ 40ms TCP setup (network)

                    + 20ms request (network)
                    + 40ms processing
                    + 20ms response (network)


                    60% of time in network overhead

                    120ms for two requests – 50% improvement!




                                                      Pipelining
                                                  RFC 2616 (1999)


0-60 with Goliath           @igrigorik
Connection setup: 50ms

                    Request 1: 300ms
                    Request 2: 250ms

                    Total time:

                     (a)   ~250 ms
                     (b)   ~300 ms
                     (c)   ~350 ms
                     (d)   ~600 ms



                                             Pipelining Quiz
                                                 RFC 2616 (1999)


0-60 with Goliath            @igrigorik
Benchmark client round-trip time (RTT),
                         not just the server processing time




                                               * a public service announcement


0-60 with Goliath                 @igrigorik
There is just one small gotcha…




                             Making HTTP Pipelining
                            Usable on the Open Web
                    http://tools.ietf.org/html/draft-nottingham-http-pipeline-01




0-60 with Goliath                   @igrigorik
conn = EM::HttpRequest.new('http://gogaruco.com')

r1 = conn.get :path => "speakers.html", :keepalive => true # 250 ms
r2 = conn.get :path => "schedule.html"               # 300 ms




 Total execution time is:                               Keep-alive what? HTTP 1.0!

 (a) 250 ms             ~ 65% truthiness
 (b) 300 ms             ~ 25% truthiness *              Good: Keep-alive + Pipelining
 (c) 550 ms             ~ 10% truthiness **              Bad: Keep-alive + Garbage


                                                               “I’m confused”



  Keep-alive: mostly works – yay!                           HTTP in the wild
  Pipelining: disabled (except in Opera)                      it’s a sad state of affairs


0-60 with Goliath                          @igrigorik
HTTP can be a high-performance transport
                         Goliath is our attempt to make it work




0-60 with Goliath    @igrigorik
Client API

                    “Sync API”       (optional) Fibers          optional async


                    async-rack   Middleware           Routing
                                                                                 0.3 ms
     Ruby, JRuby, Rubinius …     (streaming) HTTP Parser        HTTP 1.1

                                      EventMachine

                                         Network




                                                                            Goliath
                                           Optimize bottom up + minimal client API


0-60 with Goliath                        @igrigorik
EventMachine




                                         p "Starting"
                    while true do
                      timers             EM.run do
                      network_io          p "Running in EM reactor"
                      other_io           end
                    end
                                         p ”won’t get here"




                                       EventMachine Reactor
                                           concurrency without thread



0-60 with Goliath         @igrigorik
EventMachine


        Non-blocking IO requires non-blocking drivers:
          AMQP             http://github.com/tmm1/amqp
          MySQLPlus        http://github.com/igrigorik/em-mysqlplus
          Memcached        http://github.com/astro/remcached
          DNS              http://github.com/astro/em-dns
          Redis            http://github.com/madsimian/em-redis
          MongoDB          http://github.com/tmm1/rmongo
          HTTPRequest      http://github.com/igrigorik/em-http-request
          WebSocket        http://github.com/igrigorik/em-websocket
          Amazon S3        http://github.com/peritor/happening



          And many others:
          http://wiki.github.com/eventmachine/eventmachine/protocol-implementations




0-60 with Goliath                          @igrigorik
Goliath: Hands on…




0-60 with Goliath    @igrigorik
class AsyncUpload < Goliath::API                                 (streaming) HTTP Parser

  def on_headers(env, headers)
   env.logger.info 'received headers: ' + headers
  end

  def on_body(env, data)
   env.logger.info 'received data chunk: ' + data
  end

  def on_close(env)
   env.logger.info 'closing connection'
  end

  def response(env)
   # called when request processing is complete
  end

 end
                                              Async Request Processing
                                              don’t need to wait for the full request…


0-60 with Goliath                         @igrigorik
(streaming) HTTP Parser

 class Stream < Goliath::API

  def response(env)
   pt = EM.add_periodic_timer(1) { env.stream_send("hello") }

    EM.add_timer(10) do
     pt.cancel

     env.stream_send("goodbye!")
     env.stream_close
    end

   streaming_response 202, {'X-Stream' => 'Goliath’}
  end

 end
                                        Async/Streaming Response
                                                    don’t need to render full response…


0-60 with Goliath                      @igrigorik
(streaming) HTTP Parser
    class Websocket < Goliath::WebSocket

      def on_open(env)
       env.logger.info ”WebSocket opened”
      end

      def on_message(env, msg)
       env.logger.info ”WebSocket message: #{msg}”
      end

      def on_close(env)
       env.logger.info ”WebSocket closed”
      end

      def on_error(env, error)
       env.logger.error error
      end
                                                          Web-Sockets
    end                                              simple backend extension


0-60 with Goliath                       @igrigorik
Middleware    Routing



class Hello < Goliath::API

 use Goliath::Rack::Params
 use Goliath::Rack::JSONP

 use Goliath::Rack::Validation::RequestMethod, %w(GET)
 use Goliath::Rack::Validation::RequiredParam, {:key => 'echo'}

 def response(env)
  [200, {}, {pong: params['echo’]}]
 end

end

                                                                  Middleware
                                                                    No rackup file


0-60 with Goliath                       @igrigorik
Middleware    Routing
 class Bonjour < Goliath::API
  def response(env)
    [200, {}, "bonjour!"]
  end
 end

 class RackRoutes < Goliath::API

  map '/version' do
   run Proc.new { |env| [200, {}, ["Version 0.1"]] }
  end

  get "/bonjour", Bonjour

  not_found('/') do
   # run Proc. new { ... }
  end                                                          Routing
 end                                                    simple and powerful


0-60 with Goliath                          @igrigorik
Client API

               (optional) Fibers

        Middleware          Routing

          (streaming) HTTP Parser

                EventMachine

                    Network


                                                      Ruby Fibers + Goliath
                                      synchronous API for asynchronous processing



0-60 with Goliath                        @igrigorik
Ruby 1.9 Fibers are a means of creating code
                          blocks which can be paused and resumed by
                          our application (think lightweight threads,
                          minus the thread scheduler and less
                          overhead).
    f = Fiber.new {
      while true do
       Fiber.yield "Hi”
      end
    }
                                       Manual / cooperative scheduling!
    p f.resume # => Hi
    p f.resume # => Hi
    p f.resume # => Hi
                                                        Ruby 1.9 Fibers
     http://bit.ly/d2hYw0                           and cooperative scheduling


0-60 with Goliath                      @igrigorik
Fibers vs Threads: creation time much lower




                    Fibers vs Threads: memory usage is much lower




                                                               Ruby 1.9 Fibers
                                                           and cooperative scheduling
               http://bit.ly/aesXy5

0-60 with Goliath                            @igrigorik
def query(sql)
    f = Fiber.current
    conn = EventMachine::MySQL.new(:host => 'localhost')

    q = conn.query(sql)

    c.callback { f.resume(conn) }
    c.errback { f.resume(conn) }

    return Fiber.yield
   end

   EventMachine.run do                                      Exception, async!
    Fiber.new {

      res = query('select sleep(1)')
      puts "Results: #{res.fetch_row.first}"

    }.resume
   end
                             Untangling Evented Code with Fibers
                                                                        http://bit.ly/d2hYw0


0-60 with Goliath                              @igrigorik
def query(sql)
    f = Fiber.current
    conn = EventMachine::MySQL.new(:host => 'localhost')

    q = conn.query(sql)

    c.callback { f.resume(conn) }
    c.errback { f.resume(conn) }

    return Fiber.yield
   end
                                          1. Wrap into a continuation
   EventMachine.run do
    Fiber.new {

      res = query('select sleep(1)')
      puts "Results: #{res.fetch_row.first}"

    }.resume
   end
                             Untangling Evented Code with Fibers
                                                                    http://bit.ly/d2hYw0


0-60 with Goliath                               @igrigorik
def query(sql)
    f = Fiber.current
    conn = EventMachine::MySQL.new(:host => 'localhost')

    q = conn.query(sql)

    c.callback { f.resume(conn) }
    c.errback { f.resume(conn) }

    return Fiber.yield
   end
                                                    2. Pause the continuation
   EventMachine.run do
    Fiber.new {

      res = query('select sleep(1)')
      puts "Results: #{res.fetch_row.first}"

    }.resume
   end
                             Untangling Evented Code with Fibers
                                                                     http://bit.ly/d2hYw0


0-60 with Goliath                              @igrigorik
def query(sql)
    f = Fiber.current
    conn = EventMachine::MySQL.new(:host => 'localhost')

    q = conn.query(sql)

    c.callback { f.resume(conn) }
    c.errback { f.resume(conn) }                            3. Resume the continuation

    return Fiber.yield
   end

   EventMachine.run do
    Fiber.new {

      res = query('select sleep(1)')
                                                                          Fixed!
      puts "Results: #{res.fetch_row.first}"

    }.resume
   end
                             Untangling Evented Code with Fibers
                                                                     http://bit.ly/d2hYw0


0-60 with Goliath                              @igrigorik
www.goliath.io




     • Single responsibility web-services

     • Async HTTP response streaming + wraps each incoming request
                   Goliath automatically progressive notifications
     • Async HTTP request streaming +allowing us to hide the async
                     into a Ruby fiber, progressive notifications
                             complexity from the developer.
     • Multiple requests within the same VM

     • Keep-alive support
     • Pipelining support

     • Ruby API & “X-Ruby friendly”
     • Easy to maintain & test


0-60 with Goliath                           @igrigorik
require 'goliath'

            class Hello < Goliath::API

              def response(env)
               [200, {}, "Hello World"]
              end

            end

            $> ruby hello.rb -sv –p 8000 –e production




                                                           Hello World
                                                         Simple Goliath server


0-60 with Goliath                          @igrigorik
async response



      def response(env)
        conn = EM::HttpRequest.new(’http://google.com/')
        r1 = conn.aget :query => {:q => ’oredev'}

        r1.callback do
         r2 = conn.aget :query => {:q => ’goliath'}
         r2.callback { ... }
         r2.errback { ... }
        end

        r2.errback { ... }

       streaming_response 200, {}
      end
                                                           Async fun
                                                                 { { {} } } …


0-60 with Goliath                          @igrigorik
async + fiber response




     def response(env)
       conn = EM::HttpRequest.new(’http://google.com/')
       r1 = conn.get :query => {:q => ’oredev'}

        if r1.error?
          r2 = conn.get :query => {:q => ’goliath'}
        else
          # ...
        end

       [200, {}, r2.response]
     end


                                                          Async + Fibers
                                                          Ruby gives us a choice


0-60 with Goliath                           @igrigorik
EM-Synchrony:                   http://github.com/igrigorik/em-synchrony


     •   em-http-request                               •     ConnectionPool
     •   em-memcached                                  •     MultiRequest
     •   em-mongo                                      •     Iterators
     •   em-jack                                       •     Inline async
     •   mysql2                                        •     TCPSocket
     •   redis                                         •     …
     •   …



                    multi = EventMachine::Synchrony::Multi.new

                    multi.add :a, db.aquery("select sleep(1)")
                    multi.add :b, db.aquery("select sleep(1)")

                    res = multi.perform




0-60 with Goliath                               @igrigorik
describe HttpLog do


      it 'forwards to our API server' do
        with_api(HttpLog, api_options) do |api|

          get_request({}, err) do |c|
           c.response_header.status.should == 200
           c.response_header[’X-Header'].should == 'Header'
           c.response.should == 'Hello from Responder'
          end

       end
      end


     end                                               Integration Testing
                                                         simple end-to-end testing


0-60 with Goliath                         @igrigorik
http://goliath.io/




0-60 with Goliath   @igrigorik
0-60 with Goliath   @igrigorik
gem install goliath

    Goliath
    https://goliath.io/
    https://github.com/postrank-labs/goliath/



    Peepcode
    http://peepcode.com/products/eventmachine-ii
    http://peepcode.com/products/eventmachine-i




                                    Phew, time for questions?
                                    hope this convinced you to explore the area further…


0-60 with Goliath                           @igrigorik

More Related Content

What's hot

Ruby 1.9 Fibers
Ruby 1.9 FibersRuby 1.9 Fibers
Ruby 1.9 FibersKevin Ball
 
The Atmosphere Framework
The Atmosphere FrameworkThe Atmosphere Framework
The Atmosphere Frameworkjfarcand
 
Writing highly scalable WebSocket using the Atmosphere Framework and Scala
Writing highly scalable WebSocket using the Atmosphere Framework and ScalaWriting highly scalable WebSocket using the Atmosphere Framework and Scala
Writing highly scalable WebSocket using the Atmosphere Framework and Scalajfarcand
 
Websockets on the JVM: Atmosphere to the rescue!
Websockets on the JVM: Atmosphere to the rescue!Websockets on the JVM: Atmosphere to the rescue!
Websockets on the JVM: Atmosphere to the rescue!jfarcand
 
Communication in Python and the C10k problem
Communication in Python and the C10k problemCommunication in Python and the C10k problem
Communication in Python and the C10k problemJose Galarza
 
Solving anything in VCL
Solving anything in VCLSolving anything in VCL
Solving anything in VCLFastly
 
Caching the Uncacheable: Leveraging Your CDN to Cache Dynamic Content
Caching the Uncacheable: Leveraging Your CDN to Cache Dynamic ContentCaching the Uncacheable: Leveraging Your CDN to Cache Dynamic Content
Caching the Uncacheable: Leveraging Your CDN to Cache Dynamic ContentFastly
 
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...Ontico
 
Mitigating Security Threats with Fastly - Joe Williams at Fastly Altitude 2015
Mitigating Security Threats with Fastly - Joe Williams at Fastly Altitude 2015Mitigating Security Threats with Fastly - Joe Williams at Fastly Altitude 2015
Mitigating Security Threats with Fastly - Joe Williams at Fastly Altitude 2015Fastly
 
WebSockets wiith Scala and Play! Framework
WebSockets wiith Scala and Play! FrameworkWebSockets wiith Scala and Play! Framework
WebSockets wiith Scala and Play! FrameworkFabio Tiriticco
 
Stupid Boot Tricks: using ipxe and chef to get to boot management bliss
Stupid Boot Tricks: using ipxe and chef to get to boot management blissStupid Boot Tricks: using ipxe and chef to get to boot management bliss
Stupid Boot Tricks: using ipxe and chef to get to boot management blissmacslide
 
Tips for going fast in a slow world: Michael May at OSCON 2015
Tips for going fast in a slow world: Michael May at OSCON 2015Tips for going fast in a slow world: Michael May at OSCON 2015
Tips for going fast in a slow world: Michael May at OSCON 2015Fastly
 
GWT Web Socket and data serialization
GWT Web Socket and data serializationGWT Web Socket and data serialization
GWT Web Socket and data serializationGWTcon
 
Servlet 3.1 Async I/O
Servlet 3.1 Async I/OServlet 3.1 Async I/O
Servlet 3.1 Async I/OSimone Bordet
 
Rails Caching Secrets from the Edge
Rails Caching Secrets from the EdgeRails Caching Secrets from the Edge
Rails Caching Secrets from the EdgeMichael May
 
Reverse ajax in 2014
Reverse ajax in 2014Reverse ajax in 2014
Reverse ajax in 2014Nenad Pecanac
 
Going Live! with Comet
Going Live! with CometGoing Live! with Comet
Going Live! with CometSimon Willison
 

What's hot (20)

Ruby 1.9 Fibers
Ruby 1.9 FibersRuby 1.9 Fibers
Ruby 1.9 Fibers
 
The Atmosphere Framework
The Atmosphere FrameworkThe Atmosphere Framework
The Atmosphere Framework
 
Writing highly scalable WebSocket using the Atmosphere Framework and Scala
Writing highly scalable WebSocket using the Atmosphere Framework and ScalaWriting highly scalable WebSocket using the Atmosphere Framework and Scala
Writing highly scalable WebSocket using the Atmosphere Framework and Scala
 
Websockets on the JVM: Atmosphere to the rescue!
Websockets on the JVM: Atmosphere to the rescue!Websockets on the JVM: Atmosphere to the rescue!
Websockets on the JVM: Atmosphere to the rescue!
 
Communication in Python and the C10k problem
Communication in Python and the C10k problemCommunication in Python and the C10k problem
Communication in Python and the C10k problem
 
Solving anything in VCL
Solving anything in VCLSolving anything in VCL
Solving anything in VCL
 
The HTML5 WebSocket API
The HTML5 WebSocket APIThe HTML5 WebSocket API
The HTML5 WebSocket API
 
Caching the Uncacheable: Leveraging Your CDN to Cache Dynamic Content
Caching the Uncacheable: Leveraging Your CDN to Cache Dynamic ContentCaching the Uncacheable: Leveraging Your CDN to Cache Dynamic Content
Caching the Uncacheable: Leveraging Your CDN to Cache Dynamic Content
 
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...
 
Mitigating Security Threats with Fastly - Joe Williams at Fastly Altitude 2015
Mitigating Security Threats with Fastly - Joe Williams at Fastly Altitude 2015Mitigating Security Threats with Fastly - Joe Williams at Fastly Altitude 2015
Mitigating Security Threats with Fastly - Joe Williams at Fastly Altitude 2015
 
WebSockets wiith Scala and Play! Framework
WebSockets wiith Scala and Play! FrameworkWebSockets wiith Scala and Play! Framework
WebSockets wiith Scala and Play! Framework
 
Stupid Boot Tricks: using ipxe and chef to get to boot management bliss
Stupid Boot Tricks: using ipxe and chef to get to boot management blissStupid Boot Tricks: using ipxe and chef to get to boot management bliss
Stupid Boot Tricks: using ipxe and chef to get to boot management bliss
 
Tips for going fast in a slow world: Michael May at OSCON 2015
Tips for going fast in a slow world: Michael May at OSCON 2015Tips for going fast in a slow world: Michael May at OSCON 2015
Tips for going fast in a slow world: Michael May at OSCON 2015
 
GWT Web Socket and data serialization
GWT Web Socket and data serializationGWT Web Socket and data serialization
GWT Web Socket and data serialization
 
Servlet 3.1 Async I/O
Servlet 3.1 Async I/OServlet 3.1 Async I/O
Servlet 3.1 Async I/O
 
Rails Caching Secrets from the Edge
Rails Caching Secrets from the EdgeRails Caching Secrets from the Edge
Rails Caching Secrets from the Edge
 
Time for Comet?
Time for Comet?Time for Comet?
Time for Comet?
 
Speedy TDD with Rails
Speedy TDD with RailsSpeedy TDD with Rails
Speedy TDD with Rails
 
Reverse ajax in 2014
Reverse ajax in 2014Reverse ajax in 2014
Reverse ajax in 2014
 
Going Live! with Comet
Going Live! with CometGoing Live! with Comet
Going Live! with Comet
 

Similar to 0-60 with Goliath: High performance web services

Html5 web sockets - Brad Drysdale - London Web 2011-10-20
Html5 web sockets - Brad Drysdale - London Web 2011-10-20Html5 web sockets - Brad Drysdale - London Web 2011-10-20
Html5 web sockets - Brad Drysdale - London Web 2011-10-20Nathan O'Hanlon
 
7.) convergence (w automation)
7.) convergence (w automation)7.) convergence (w automation)
7.) convergence (w automation)Jeff Green
 
ALOHA Load Balancer - Rackable Appliance
ALOHA Load Balancer - Rackable ApplianceALOHA Load Balancer - Rackable Appliance
ALOHA Load Balancer - Rackable ApplianceEXCELIANCE
 
What can you do with lambda in 2020
What can you do with lambda in 2020What can you do with lambda in 2020
What can you do with lambda in 2020Yan Cui
 
What can you do with lambda in 2020
What can you do with lambda in 2020What can you do with lambda in 2020
What can you do with lambda in 2020Yan Cui
 
[E4]triple s deview
[E4]triple s deview[E4]triple s deview
[E4]triple s deviewNAVER D2
 
Webinar NETGEAR - Soluzioni Switch Smart 10 gigabit & how to eliminate bottle...
Webinar NETGEAR - Soluzioni Switch Smart 10 gigabit & how to eliminate bottle...Webinar NETGEAR - Soluzioni Switch Smart 10 gigabit & how to eliminate bottle...
Webinar NETGEAR - Soluzioni Switch Smart 10 gigabit & how to eliminate bottle...Netgear Italia
 
Fast i pv4 lookup using local memory
Fast i pv4 lookup using local memoryFast i pv4 lookup using local memory
Fast i pv4 lookup using local memoryVipin Varghese
 
New idc architecture
New idc architectureNew idc architecture
New idc architectureMason Mei
 
JavaZone 2016 : MQTT and CoAP for the Java Developer
JavaZone 2016 : MQTT and CoAP for the Java DeveloperJavaZone 2016 : MQTT and CoAP for the Java Developer
JavaZone 2016 : MQTT and CoAP for the Java DeveloperMark West
 
SSL: limitations, bad practices and how to do it right
SSL: limitations, bad practices  and how to do it rightSSL: limitations, bad practices  and how to do it right
SSL: limitations, bad practices and how to do it rightTiago Mendo
 
Chirp 2010: Scaling Twitter
Chirp 2010: Scaling TwitterChirp 2010: Scaling Twitter
Chirp 2010: Scaling TwitterJohn Adams
 
IoT Day 2013 - Madrid
IoT Day 2013 - MadridIoT Day 2013 - Madrid
IoT Day 2013 - Madridwaltercolitti
 
Extending the Yahoo Streaming Benchmark + MapR Benchmarks
Extending the Yahoo Streaming Benchmark + MapR BenchmarksExtending the Yahoo Streaming Benchmark + MapR Benchmarks
Extending the Yahoo Streaming Benchmark + MapR BenchmarksJamie Grier
 

Similar to 0-60 with Goliath: High performance web services (20)

Html5 web sockets - Brad Drysdale - London Web 2011-10-20
Html5 web sockets - Brad Drysdale - London Web 2011-10-20Html5 web sockets - Brad Drysdale - London Web 2011-10-20
Html5 web sockets - Brad Drysdale - London Web 2011-10-20
 
HTTP/2 (2017)
HTTP/2 (2017)HTTP/2 (2017)
HTTP/2 (2017)
 
SPDY Talk
SPDY TalkSPDY Talk
SPDY Talk
 
7.) convergence (w automation)
7.) convergence (w automation)7.) convergence (w automation)
7.) convergence (w automation)
 
ALOHA Load Balancer - Rackable Appliance
ALOHA Load Balancer - Rackable ApplianceALOHA Load Balancer - Rackable Appliance
ALOHA Load Balancer - Rackable Appliance
 
What can you do with lambda in 2020
What can you do with lambda in 2020What can you do with lambda in 2020
What can you do with lambda in 2020
 
UDP Offload Engine (UOE)
UDP Offload Engine (UOE)UDP Offload Engine (UOE)
UDP Offload Engine (UOE)
 
What can you do with lambda in 2020
What can you do with lambda in 2020What can you do with lambda in 2020
What can you do with lambda in 2020
 
[E4]triple s deview
[E4]triple s deview[E4]triple s deview
[E4]triple s deview
 
Webinar NETGEAR - Soluzioni Switch Smart 10 gigabit & how to eliminate bottle...
Webinar NETGEAR - Soluzioni Switch Smart 10 gigabit & how to eliminate bottle...Webinar NETGEAR - Soluzioni Switch Smart 10 gigabit & how to eliminate bottle...
Webinar NETGEAR - Soluzioni Switch Smart 10 gigabit & how to eliminate bottle...
 
Fast i pv4 lookup using local memory
Fast i pv4 lookup using local memoryFast i pv4 lookup using local memory
Fast i pv4 lookup using local memory
 
New idc architecture
New idc architectureNew idc architecture
New idc architecture
 
Varnish Cache
Varnish CacheVarnish Cache
Varnish Cache
 
JavaZone 2016 : MQTT and CoAP for the Java Developer
JavaZone 2016 : MQTT and CoAP for the Java DeveloperJavaZone 2016 : MQTT and CoAP for the Java Developer
JavaZone 2016 : MQTT and CoAP for the Java Developer
 
SSL: limitations, bad practices and how to do it right
SSL: limitations, bad practices  and how to do it rightSSL: limitations, bad practices  and how to do it right
SSL: limitations, bad practices and how to do it right
 
Chirp 2010: Scaling Twitter
Chirp 2010: Scaling TwitterChirp 2010: Scaling Twitter
Chirp 2010: Scaling Twitter
 
Websocket
WebsocketWebsocket
Websocket
 
IoT Day 2013 - Madrid
IoT Day 2013 - MadridIoT Day 2013 - Madrid
IoT Day 2013 - Madrid
 
Graphite
GraphiteGraphite
Graphite
 
Extending the Yahoo Streaming Benchmark + MapR Benchmarks
Extending the Yahoo Streaming Benchmark + MapR BenchmarksExtending the Yahoo Streaming Benchmark + MapR Benchmarks
Extending the Yahoo Streaming Benchmark + MapR Benchmarks
 

More from Ilya Grigorik

Pagespeed what, why, and how it works
Pagespeed   what, why, and how it worksPagespeed   what, why, and how it works
Pagespeed what, why, and how it worksIlya Grigorik
 
Making the web fast(er) - RailsConf 2012
Making the web fast(er) - RailsConf 2012Making the web fast(er) - RailsConf 2012
Making the web fast(er) - RailsConf 2012Ilya Grigorik
 
Ruby in the Browser - RubyConf 2011
Ruby in the Browser - RubyConf 2011Ruby in the Browser - RubyConf 2011
Ruby in the Browser - RubyConf 2011Ilya Grigorik
 
Intelligent Ruby + Machine Learning
Intelligent Ruby + Machine LearningIntelligent Ruby + Machine Learning
Intelligent Ruby + Machine LearningIlya Grigorik
 
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9Ilya Grigorik
 
No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010Ilya Grigorik
 
Real-time Ruby for the Real-time Web
Real-time Ruby for the Real-time WebReal-time Ruby for the Real-time Web
Real-time Ruby for the Real-time WebIlya Grigorik
 
Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09
Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09
Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09Ilya Grigorik
 
Leveraging Social Media - Strategies & Tactics - PostRank
Leveraging Social Media - Strategies & Tactics - PostRankLeveraging Social Media - Strategies & Tactics - PostRank
Leveraging Social Media - Strategies & Tactics - PostRankIlya Grigorik
 
Building Mini Google in Ruby
Building Mini Google in RubyBuilding Mini Google in Ruby
Building Mini Google in RubyIlya Grigorik
 
Taming The RSS Beast
Taming The  RSS  BeastTaming The  RSS  Beast
Taming The RSS BeastIlya Grigorik
 

More from Ilya Grigorik (11)

Pagespeed what, why, and how it works
Pagespeed   what, why, and how it worksPagespeed   what, why, and how it works
Pagespeed what, why, and how it works
 
Making the web fast(er) - RailsConf 2012
Making the web fast(er) - RailsConf 2012Making the web fast(er) - RailsConf 2012
Making the web fast(er) - RailsConf 2012
 
Ruby in the Browser - RubyConf 2011
Ruby in the Browser - RubyConf 2011Ruby in the Browser - RubyConf 2011
Ruby in the Browser - RubyConf 2011
 
Intelligent Ruby + Machine Learning
Intelligent Ruby + Machine LearningIntelligent Ruby + Machine Learning
Intelligent Ruby + Machine Learning
 
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
 
No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010
 
Real-time Ruby for the Real-time Web
Real-time Ruby for the Real-time WebReal-time Ruby for the Real-time Web
Real-time Ruby for the Real-time Web
 
Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09
Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09
Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09
 
Leveraging Social Media - Strategies & Tactics - PostRank
Leveraging Social Media - Strategies & Tactics - PostRankLeveraging Social Media - Strategies & Tactics - PostRank
Leveraging Social Media - Strategies & Tactics - PostRank
 
Building Mini Google in Ruby
Building Mini Google in RubyBuilding Mini Google in Ruby
Building Mini Google in Ruby
 
Taming The RSS Beast
Taming The  RSS  BeastTaming The  RSS  Beast
Taming The RSS Beast
 

Recently uploaded

Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1DianaGray10
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.YounusS2
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfDaniel Santiago Silva Capera
 
Empowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintEmpowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintMahmoud Rabie
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPathCommunity
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAshyamraj55
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding TeamAdam Moalla
 
NIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopNIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopBachir Benyammi
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Will Schroeder
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdfPedro Manuel
 
Designing A Time bound resource download URL
Designing A Time bound resource download URLDesigning A Time bound resource download URL
Designing A Time bound resource download URLRuncy Oommen
 
20200723_insight_release_plan_v6.pdf20200723_insight_release_plan_v6.pdf
20200723_insight_release_plan_v6.pdf20200723_insight_release_plan_v6.pdf20200723_insight_release_plan_v6.pdf20200723_insight_release_plan_v6.pdf
20200723_insight_release_plan_v6.pdf20200723_insight_release_plan_v6.pdfJamie (Taka) Wang
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfinfogdgmi
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024SkyPlanner
 
Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?SANGHEE SHIN
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioChristian Posta
 
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesMd Hossain Ali
 
RAG Patterns and Vector Search in Generative AI
RAG Patterns and Vector Search in Generative AIRAG Patterns and Vector Search in Generative AI
RAG Patterns and Vector Search in Generative AIUdaiappa Ramachandran
 
Introduction to Quantum Computing
Introduction to Quantum ComputingIntroduction to Quantum Computing
Introduction to Quantum ComputingGDSC PJATK
 
Cloud Revolution: Exploring the New Wave of Serverless Spatial Data
Cloud Revolution: Exploring the New Wave of Serverless Spatial DataCloud Revolution: Exploring the New Wave of Serverless Spatial Data
Cloud Revolution: Exploring the New Wave of Serverless Spatial DataSafe Software
 

Recently uploaded (20)

Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
 
Empowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintEmpowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership Blueprint
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation Developers
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team
 
NIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopNIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 Workshop
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdf
 
Designing A Time bound resource download URL
Designing A Time bound resource download URLDesigning A Time bound resource download URL
Designing A Time bound resource download URL
 
20200723_insight_release_plan_v6.pdf20200723_insight_release_plan_v6.pdf
20200723_insight_release_plan_v6.pdf20200723_insight_release_plan_v6.pdf20200723_insight_release_plan_v6.pdf20200723_insight_release_plan_v6.pdf
20200723_insight_release_plan_v6.pdf20200723_insight_release_plan_v6.pdf
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdf
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024
 
Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?Do we need a new standard for visualizing the invisible?
Do we need a new standard for visualizing the invisible?
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and Istio
 
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
 
RAG Patterns and Vector Search in Generative AI
RAG Patterns and Vector Search in Generative AIRAG Patterns and Vector Search in Generative AI
RAG Patterns and Vector Search in Generative AI
 
Introduction to Quantum Computing
Introduction to Quantum ComputingIntroduction to Quantum Computing
Introduction to Quantum Computing
 
Cloud Revolution: Exploring the New Wave of Serverless Spatial Data
Cloud Revolution: Exploring the New Wave of Serverless Spatial DataCloud Revolution: Exploring the New Wave of Serverless Spatial Data
Cloud Revolution: Exploring the New Wave of Serverless Spatial Data
 

0-60 with Goliath: High performance web services

  • 1. 0-60 with Goliath Building high performance (Ruby) web-services Ilya Grigorik @igrigorik 0-60 with Goliath @igrigorik
  • 2. - “Social Analytics” - Goliath == v3 API stack - Rails frontend - Open sourced in 2011 - Ruby backend - Growing community - 95%+ of traffic via API’s + + Brief History Goliath @ PostRank 0-60 with Goliath @igrigorik
  • 3. Rails HTTP API … HTTP API HTTP API HTTP API SQL SQL SQL SQL SQL … SQL Solr • Separate logical & physical services • Easy to tune, easy to maintain, easy to “scale” PRO • Stable code, fault-tolerance • Higher upfront ops cost CON • Lots of cross-service communication 0-60 with Goliath @igrigorik
  • 4. 0-60 with Goliath @igrigorik
  • 5. www.goliath.io • Single responsibility web-services • Async HTTP response streaming + progressive notifications • Async HTTP request streaming + progressive notifications • Multiple requests within the same VM … lower ops costs • Keep-alive support … full HTTP 1.1 support • Pipelining support • Ruby API & “X-Ruby friendly” … Ruby polyglot! • Easy to maintain & test 0-60 with Goliath @igrigorik
  • 6. HTTP Pipelining + Keep-Alive 101 perhaps not as simple as it may seem… 0-60 with Goliath @igrigorik
  • 7. conn = EM::HttpRequest.new('http://oredev.org') r1 = conn.get :path => ”2011/speakers", :keepalive => true # 250 ms r2 = conn.get :path => ”2011/faq" # 300 ms # wait until done … Total execution time is: Answer: (a) 250 ms ~ 65% truthiness (b) 300 ms ~ 25% truthiness * All of the above! (c) 550 ms ~ 10% truthiness ** HTTP Quiz this is not a trick question… 0-60 with Goliath @igrigorik
  • 8. Client Server 20 ms TCP handshake HTTP Request 40 ms • headers, body processing Multi-part body (*) Terminate connection + 40ms TCP setup (network) + 20ms request (network) + 40ms processing + 20ms response (network) HTTP 1.0 66% of time in network overhead RFC 1945 (1996) 0-60 with Goliath @igrigorik
  • 9. Research done at Google shows that an increase from 5Mbps to 10Mbps results in a disappointing 5% improvement in page load times. Or put slightly differently, a 10Mbps connection, on average uses only 16% of its capacity. http://bit.ly/oemX0I 0-60 with Goliath @igrigorik
  • 10. Keep-alive • Re-use open connection • No multiplexing, serial • Default to “on” Pipelining • No multiplexing • Parallel requests HTTP 1.1 RFC 2616 (1999) 0-60 with Goliath @igrigorik
  • 11. + 40ms TCP setup (network) + 20ms request (network) + 40ms processing + 20ms response (network) x 40ms TCP setup (network) + 20ms request (network) + 40ms processing + 20ms response (network) 200ms for two requests Small win over HTTP 1.0 Keep-alive RFC 2616 (1999) 0-60 with Goliath @igrigorik
  • 12. Net:HTTP Connection: close < ugh! Keep-alive RFC 2616 (1999) 0-60 with Goliath @igrigorik
  • 13. + 40ms TCP setup (network) + 20ms request (network) + 40ms processing + 20ms response (network) 60% of time in network overhead 120ms for two requests – 50% improvement! Pipelining RFC 2616 (1999) 0-60 with Goliath @igrigorik
  • 14. Connection setup: 50ms Request 1: 300ms Request 2: 250ms Total time: (a) ~250 ms (b) ~300 ms (c) ~350 ms (d) ~600 ms Pipelining Quiz RFC 2616 (1999) 0-60 with Goliath @igrigorik
  • 15. Benchmark client round-trip time (RTT), not just the server processing time * a public service announcement 0-60 with Goliath @igrigorik
  • 16. There is just one small gotcha… Making HTTP Pipelining Usable on the Open Web http://tools.ietf.org/html/draft-nottingham-http-pipeline-01 0-60 with Goliath @igrigorik
  • 17. conn = EM::HttpRequest.new('http://gogaruco.com') r1 = conn.get :path => "speakers.html", :keepalive => true # 250 ms r2 = conn.get :path => "schedule.html" # 300 ms Total execution time is: Keep-alive what? HTTP 1.0! (a) 250 ms ~ 65% truthiness (b) 300 ms ~ 25% truthiness * Good: Keep-alive + Pipelining (c) 550 ms ~ 10% truthiness ** Bad: Keep-alive + Garbage “I’m confused” Keep-alive: mostly works – yay! HTTP in the wild Pipelining: disabled (except in Opera) it’s a sad state of affairs 0-60 with Goliath @igrigorik
  • 18. HTTP can be a high-performance transport Goliath is our attempt to make it work 0-60 with Goliath @igrigorik
  • 19. Client API “Sync API” (optional) Fibers optional async async-rack Middleware Routing 0.3 ms Ruby, JRuby, Rubinius … (streaming) HTTP Parser HTTP 1.1 EventMachine Network Goliath Optimize bottom up + minimal client API 0-60 with Goliath @igrigorik
  • 20. EventMachine p "Starting" while true do timers EM.run do network_io p "Running in EM reactor" other_io end end p ”won’t get here" EventMachine Reactor concurrency without thread 0-60 with Goliath @igrigorik
  • 21. EventMachine Non-blocking IO requires non-blocking drivers: AMQP http://github.com/tmm1/amqp MySQLPlus http://github.com/igrigorik/em-mysqlplus Memcached http://github.com/astro/remcached DNS http://github.com/astro/em-dns Redis http://github.com/madsimian/em-redis MongoDB http://github.com/tmm1/rmongo HTTPRequest http://github.com/igrigorik/em-http-request WebSocket http://github.com/igrigorik/em-websocket Amazon S3 http://github.com/peritor/happening And many others: http://wiki.github.com/eventmachine/eventmachine/protocol-implementations 0-60 with Goliath @igrigorik
  • 22. Goliath: Hands on… 0-60 with Goliath @igrigorik
  • 23. class AsyncUpload < Goliath::API (streaming) HTTP Parser def on_headers(env, headers) env.logger.info 'received headers: ' + headers end def on_body(env, data) env.logger.info 'received data chunk: ' + data end def on_close(env) env.logger.info 'closing connection' end def response(env) # called when request processing is complete end end Async Request Processing don’t need to wait for the full request… 0-60 with Goliath @igrigorik
  • 24. (streaming) HTTP Parser class Stream < Goliath::API def response(env) pt = EM.add_periodic_timer(1) { env.stream_send("hello") } EM.add_timer(10) do pt.cancel env.stream_send("goodbye!") env.stream_close end streaming_response 202, {'X-Stream' => 'Goliath’} end end Async/Streaming Response don’t need to render full response… 0-60 with Goliath @igrigorik
  • 25. (streaming) HTTP Parser class Websocket < Goliath::WebSocket def on_open(env) env.logger.info ”WebSocket opened” end def on_message(env, msg) env.logger.info ”WebSocket message: #{msg}” end def on_close(env) env.logger.info ”WebSocket closed” end def on_error(env, error) env.logger.error error end Web-Sockets end simple backend extension 0-60 with Goliath @igrigorik
  • 26. Middleware Routing class Hello < Goliath::API use Goliath::Rack::Params use Goliath::Rack::JSONP use Goliath::Rack::Validation::RequestMethod, %w(GET) use Goliath::Rack::Validation::RequiredParam, {:key => 'echo'} def response(env) [200, {}, {pong: params['echo’]}] end end Middleware No rackup file 0-60 with Goliath @igrigorik
  • 27. Middleware Routing class Bonjour < Goliath::API def response(env) [200, {}, "bonjour!"] end end class RackRoutes < Goliath::API map '/version' do run Proc.new { |env| [200, {}, ["Version 0.1"]] } end get "/bonjour", Bonjour not_found('/') do # run Proc. new { ... } end Routing end simple and powerful 0-60 with Goliath @igrigorik
  • 28. Client API (optional) Fibers Middleware Routing (streaming) HTTP Parser EventMachine Network Ruby Fibers + Goliath synchronous API for asynchronous processing 0-60 with Goliath @igrigorik
  • 29. Ruby 1.9 Fibers are a means of creating code blocks which can be paused and resumed by our application (think lightweight threads, minus the thread scheduler and less overhead). f = Fiber.new { while true do Fiber.yield "Hi” end } Manual / cooperative scheduling! p f.resume # => Hi p f.resume # => Hi p f.resume # => Hi Ruby 1.9 Fibers http://bit.ly/d2hYw0 and cooperative scheduling 0-60 with Goliath @igrigorik
  • 30. Fibers vs Threads: creation time much lower Fibers vs Threads: memory usage is much lower Ruby 1.9 Fibers and cooperative scheduling http://bit.ly/aesXy5 0-60 with Goliath @igrigorik
  • 31. def query(sql) f = Fiber.current conn = EventMachine::MySQL.new(:host => 'localhost') q = conn.query(sql) c.callback { f.resume(conn) } c.errback { f.resume(conn) } return Fiber.yield end EventMachine.run do Exception, async! Fiber.new { res = query('select sleep(1)') puts "Results: #{res.fetch_row.first}" }.resume end Untangling Evented Code with Fibers http://bit.ly/d2hYw0 0-60 with Goliath @igrigorik
  • 32. def query(sql) f = Fiber.current conn = EventMachine::MySQL.new(:host => 'localhost') q = conn.query(sql) c.callback { f.resume(conn) } c.errback { f.resume(conn) } return Fiber.yield end 1. Wrap into a continuation EventMachine.run do Fiber.new { res = query('select sleep(1)') puts "Results: #{res.fetch_row.first}" }.resume end Untangling Evented Code with Fibers http://bit.ly/d2hYw0 0-60 with Goliath @igrigorik
  • 33. def query(sql) f = Fiber.current conn = EventMachine::MySQL.new(:host => 'localhost') q = conn.query(sql) c.callback { f.resume(conn) } c.errback { f.resume(conn) } return Fiber.yield end 2. Pause the continuation EventMachine.run do Fiber.new { res = query('select sleep(1)') puts "Results: #{res.fetch_row.first}" }.resume end Untangling Evented Code with Fibers http://bit.ly/d2hYw0 0-60 with Goliath @igrigorik
  • 34. def query(sql) f = Fiber.current conn = EventMachine::MySQL.new(:host => 'localhost') q = conn.query(sql) c.callback { f.resume(conn) } c.errback { f.resume(conn) } 3. Resume the continuation return Fiber.yield end EventMachine.run do Fiber.new { res = query('select sleep(1)') Fixed! puts "Results: #{res.fetch_row.first}" }.resume end Untangling Evented Code with Fibers http://bit.ly/d2hYw0 0-60 with Goliath @igrigorik
  • 35. www.goliath.io • Single responsibility web-services • Async HTTP response streaming + wraps each incoming request Goliath automatically progressive notifications • Async HTTP request streaming +allowing us to hide the async into a Ruby fiber, progressive notifications complexity from the developer. • Multiple requests within the same VM • Keep-alive support • Pipelining support • Ruby API & “X-Ruby friendly” • Easy to maintain & test 0-60 with Goliath @igrigorik
  • 36. require 'goliath' class Hello < Goliath::API def response(env) [200, {}, "Hello World"] end end $> ruby hello.rb -sv –p 8000 –e production Hello World Simple Goliath server 0-60 with Goliath @igrigorik
  • 37. async response def response(env) conn = EM::HttpRequest.new(’http://google.com/') r1 = conn.aget :query => {:q => ’oredev'} r1.callback do r2 = conn.aget :query => {:q => ’goliath'} r2.callback { ... } r2.errback { ... } end r2.errback { ... } streaming_response 200, {} end Async fun { { {} } } … 0-60 with Goliath @igrigorik
  • 38. async + fiber response def response(env) conn = EM::HttpRequest.new(’http://google.com/') r1 = conn.get :query => {:q => ’oredev'} if r1.error? r2 = conn.get :query => {:q => ’goliath'} else # ... end [200, {}, r2.response] end Async + Fibers Ruby gives us a choice 0-60 with Goliath @igrigorik
  • 39. EM-Synchrony: http://github.com/igrigorik/em-synchrony • em-http-request • ConnectionPool • em-memcached • MultiRequest • em-mongo • Iterators • em-jack • Inline async • mysql2 • TCPSocket • redis • … • … multi = EventMachine::Synchrony::Multi.new multi.add :a, db.aquery("select sleep(1)") multi.add :b, db.aquery("select sleep(1)") res = multi.perform 0-60 with Goliath @igrigorik
  • 40. describe HttpLog do it 'forwards to our API server' do with_api(HttpLog, api_options) do |api| get_request({}, err) do |c| c.response_header.status.should == 200 c.response_header[’X-Header'].should == 'Header' c.response.should == 'Hello from Responder' end end end end Integration Testing simple end-to-end testing 0-60 with Goliath @igrigorik
  • 42. 0-60 with Goliath @igrigorik
  • 43. gem install goliath Goliath https://goliath.io/ https://github.com/postrank-labs/goliath/ Peepcode http://peepcode.com/products/eventmachine-ii http://peepcode.com/products/eventmachine-i Phew, time for questions? hope this convinced you to explore the area further… 0-60 with Goliath @igrigorik