SlideShare uma empresa Scribd logo
1 de 67
Baixar para ler offline
Ruby Proxies for Scale, Performance
    and Monitoring

                                                                            Ilya Grigorik
                                                                                      @igrigorik



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
postrank.com/topic/ruby




                              The slides…                         Twitter                           My blog


Ruby Proxies + EventMachine       http://bit.ly/railsconf-proxy             @igrigorik #railsconf
Code + Examples                                           EventMachine




                     Misc                                           Proxies

Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Proxy Love



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
“Rails, Django, Seaside, Grails…” cant scale.




                                              Myth: Slow Frameworks



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
The Proxy Solution



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy      @igrigorik #railsconf
The “More” Proxy Solution



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Transparent Scalability



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy     @igrigorik #railsconf
Load Balancer

                                                       Reverse Proxy                      App Server




                                   MySQL Proxy



                                                                    Proxy as Middleware
                                                                                          middleware ftw!




Ruby Proxies + EventMachine         http://bit.ly/railsconf-proxy        @igrigorik #railsconf
90% use case


                        %w*Transparent Intercepting Caching …+
                                                                  There are many different types!




Ruby Proxies + EventMachine       http://bit.ly/railsconf-proxy          @igrigorik #railsconf
Transparent
                                                              HAProxy




                              App server A                        App server B




                              Transparent, Cut-Through Proxy



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy        @igrigorik #railsconf
Transparent Proxy = Scalability Power Tool



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Proxy                                                               Proxy




        App server A            App server B                             App server C




                                               Problem: Staging Environment
          Production




Ruby Proxies + EventMachine              http://bit.ly/railsconf-proxy    @igrigorik #railsconf
Simulating traffic?

                                                              Proxy

        Duplication




                                   App server C




                              “Representative Load / Staging”



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy           @igrigorik #railsconf
github.com/igrigorik/autoperf



                                                              Replay log data, rinse, repeat



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy        @igrigorik #railsconf
Profile of queries has changed                                              Fail
          Load on production has changed                                              Fail
          Parallel environment                                                        Fail
          Slower release cycle                                                        Fail




                                                                   Staging fail.



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Duplex Ruby Proxy, FTW!

                                                                      Production




     Real (production) traffic
                                                                     Benchmark




                                                                   Benchmarking Proxy
                                                                                 flash of the obvious




Ruby Proxies + EventMachine        http://bit.ly/railsconf-proxy         @igrigorik #railsconf
github.com/igrigorik/em-proxy
         Proxy DSL FTW!




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
EventMachine: Speed + Convenience
                                  building high performance network apps in Ruby




Ruby Proxies + EventMachine       http://bit.ly/railsconf-proxy   @igrigorik #railsconf
p quot;Startingquot;
                                 while true do
                                                               EM.run do
                                   timers
                                                                p quot;Running in EM reactorquot;
                                   network_io
                                                               end
                                   other_io
                                 end
                                                               puts quot;Almost donequot;




                                                         EventMachine Reactor
                                                              concurrency without threads




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy       @igrigorik #railsconf
p quot;Startingquot;
                                 while true do
                                                              EM.run do
                                   timers
                                                               p quot;Running in EM reactorquot;
                                   network_io
                                                              end
                                   other_io
                                 end
                                                              puts quot;Almost donequot;


                                                         EventMachine Reactor
                                                              concurrency without threads




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy       @igrigorik #railsconf
C++ core


                                         Easy concurrency
                                         without threading




                                                         EventMachine Reactor
                                                              concurrency without threads




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy       @igrigorik #railsconf
http = EM::HttpRequest.new('http://site.com/').get

                               http.callback {
                                p http.response
                               }

                              # ... do other work, until callback fires.




                                      Event = IO event + block or lambda call



                                                          EventMachine Reactor
                                                               concurrency without threads




Ruby Proxies + EventMachine    http://bit.ly/railsconf-proxy       @igrigorik #railsconf
http = EM::HttpRequest.new('http://site.com/').get

                              http.callback {
                               p http.response
                              }

                              # ... do other work, until callback fires.




                                     Event = IO event + block or lambda call



                                                         EventMachine Reactor
                                                              concurrency without threads




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy       @igrigorik #railsconf
EM.run do
         EM.add_timer(1) { p quot;1 second laterquot; }
         EM.add_periodic_timer(5) { p quot;every 5 secondsquot;}
         EM.defer { long_running_task() }
        end


        class Server < EM::Connection
          def receive_data(data)
           send_data(quot;Pong; #{data}quot;)
          end

         def unbind
          p [:connection_completed]
         end
        end


        EM.run do
         EM.start_server quot;0.0.0.0quot;, 3000, Server
        end




Ruby Proxies + EventMachine    http://bit.ly/railsconf-proxy   @igrigorik #railsconf
EM.run do
         EM.add_timer(1) { p quot;1 second laterquot; }
         EM.add_periodic_timer(5) { p quot;every 5 secondsquot;}
         EM.defer { long_running_task() }
        end


        class Server < EM::Connection
          def receive_data(data)
           send_data(quot;Pong; #{data}quot;)                          Connection Handler
          end

         def unbind
          p [:connection_completed]
         end
        end


        EM.run do                                                    Start Reactor
         EM.start_server quot;0.0.0.0quot;, 3000, Server
        end




Ruby Proxies + EventMachine    http://bit.ly/railsconf-proxy   @igrigorik #railsconf
http://bit.ly/aiderss-eventmachine
                              by Dan Sinclair (Twitter: @dj2sincl)



Ruby Proxies + EventMachine         http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Proxies for Monitoring, Performance and Scale
                                                    welcome to the wonderful world of…




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy     @igrigorik #railsconf
Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn|
      conn.server :name, :host => quot;127.0.0.1quot;, :port => 81

       conn.on_data do |data|
        # ...
       end
                                                                         Relay Server
       conn.on_response do |server, resp|
        # ...
       end

      conn.on_finish do
       # ...
      end
     end

                                                                               EM-Proxy
                                                  www.github.com/igrigorik/em-proxy




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn|
      conn.server :name, :host => quot;127.0.0.1quot;, :port => 81

       conn.on_data do |data|
        # ...
       end
                                                                 Process incoming data
       conn.on_response do |server, resp|
        # ...
       end

      conn.on_finish do
       # ...
      end
     end

                                                                               EM-Proxy
                                                  www.github.com/igrigorik/em-proxy




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn|
      conn.server :name, :host => quot;127.0.0.1quot;, :port => 81

       conn.on_data do |data|
        # ...
       end
                                                                 Process response data
       conn.on_response do |server, resp|
        # ...
       end

      conn.on_finish do
       # ...
      end
     end

                                                                               EM-Proxy
                                                  www.github.com/igrigorik/em-proxy




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn|
      conn.server :name, :host => quot;127.0.0.1quot;, :port => 81

       conn.on_data do |data|
        # ...
       end

       conn.on_response do |server, resp|
        # ...
       end
                                                                   Post-processing step
      conn.on_finish do
       # ...
      end
     end

                                                                               EM-Proxy
                                                  www.github.com/igrigorik/em-proxy




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
%w[ <Transparent> Intercepting Caching … +
                                                              solution for every problem




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy     @igrigorik #railsconf
Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn|
      conn.server :srv, :host => quot;127.0.0.1quot;, :port => 81

       # modify / process request stream
       conn.on_data do |data|
        p [:on_data, data]
        data
       end                                                       No data modifications

      # modify / process response stream
      conn.on_response do |server, resp|
       p [:on_response, server, resp]
       resp
      end
     end

                                                              Port-Forwarding
                                                                         transparent proxy




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn|
      conn.server :srv, :host => quot;127.0.0.1quot;, :port => 81

       conn.on_data do |data|
        data
       end

      conn.on_response do |backend, resp|                               Alter response
       resp.gsub(/hello/, 'good bye')
      end
     end



                                                      Port-Forwarding + Alter
                                                                         transparent proxy




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
%w[ Transparent <Intercepting> Caching … +
                                                              solution for every problem




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy     @igrigorik #railsconf
Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn|
  @start = Time.now
  @data = Hash.new(quot;quot;)

                                                                                 Prod + Test
  conn.server :prod, :host => quot;127.0.0.1quot;, :port => 81
  conn.server :test, :host => quot;127.0.0.1quot;, :port => 82

  conn.on_data do |data|
   data.gsub(/User-Agent: .*?rn/, 'User-Agent: em-proxyrn')
  end

  conn.on_response do |server, resp|
   @data[server] += resp
   resp if server == :prod
  end

  conn.on_finish do
   p [:on_finish, Time.now - @start]
   p @data
  end
 end
                                       Duplex HTTP: Benchmarking
                                                                        Intercepting proxy



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn|
  @start = Time.now
  @data = Hash.new(quot;quot;)

  conn.server :prod, :host => quot;127.0.0.1quot;, :port => 81
  conn.server :test, :host => quot;127.0.0.1quot;, :port => 82

  conn.on_data do |data|
   data.gsub(/User-Agent: .*?rn/, 'User-Agent: em-proxyrn')
  end

  conn.on_response do |server, resp|
                                                              Respond from production
   @data[server] += resp
   resp if server == :prod
  end

  conn.on_finish do
   p [:on_finish, Time.now - @start]
   p @data
  end
 end
                                       Duplex HTTP: Benchmarking
                                                                        Intercepting proxy



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn|
  @start = Time.now
  @data = Hash.new(quot;quot;)

  conn.server :prod, :host => quot;127.0.0.1quot;, :port => 81
  conn.server :test, :host => quot;127.0.0.1quot;, :port => 82

  conn.on_data do |data|
   data.gsub(/User-Agent: .*?rn/, 'User-Agent: em-proxyrn')
  end

  conn.on_response do |server, resp|
   @data[server] += resp
   resp if server == :prod
  end
                                                              Run post-processing
  conn.on_finish do
   p [:on_finish, Time.now - @start]
   p @data
  end
 end
                                       Duplex HTTP: Benchmarking
                                                                        Intercepting proxy



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
[ilya@igvita]      >   ruby examples/appserver.rb 81
 [ilya@igvita]      >   ruby examples/appserver.rb 82
 [ilya@igvita]      >   ruby examples/line_interceptor.rb
 [ilya@igvita]      >   curl localhost




 >> [:on_finish, 1.008561]

 >> {:prod=>quot;HTTP/1.1 200 OKrnConnection: closernDate: Fri, 01 May 2009
 04:20:00 GMTrnContent-Type: text/plainrnrnhello world: 0quot;,

     :test=>quot;HTTP/1.1 200 OKrnConnection: closernDate: Fri, 01 May 2009
 04:20:00 GMTrnContent-Type: text/plainrnrnhello world: 1quot;}




                                           Duplex HTTP: Benchmarking
                                                                            Intercepting proxy



Ruby Proxies + EventMachine       http://bit.ly/railsconf-proxy   @igrigorik #railsconf
[ilya@igvita]      >   ruby examples/appserver.rb 81
 [ilya@igvita]      >   ruby examples/appserver.rb 82
 [ilya@igvita]      >   ruby examples/line_interceptor.rb
 [ilya@igvita]      >   curl localhost

                                                                                    STDOUT
 [:on_finish, 1.008561]

 {:prod=>quot;HTTP/1.1 200 OKrnConnection: closernDate: Fri,
 01 May 2009 04:20:00 GMTrnContent-Type:
 text/plainrnrnhello world: 0quot;,

   :test=>quot;HTTP/1.1 200 OKrnConnection: closernDate: Fri,
 01 May 2009 04:20:00 GMTrnContent-Type:
 text/plainrnrnhello world: 1quot;}

                                           Duplex HTTP: Benchmarking
                                                                            Intercepting proxy



Ruby Proxies + EventMachine       http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Same response, different
                                                                    turnaround time




                                                               Different response body!




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Woops!




                                                              Validating Proxy
                                                              easy, real-time diagnostics




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Hacking SMTP
                                                                          for fun and profit




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Proxy.start(:host => quot;0.0.0.0quot;, :port => 2524) do |conn|
  conn.server :srv, :host => quot;127.0.0.1quot;, :port => 2525

  # RCPT TO:<name@address.com>rn
  RCPT_CMD = /RCPT TO:<(.*)?>rn/
                                                                 Intercept Addressee
  conn.on_data do |data|

    if rcpt = data.match(RCPT_CMD)
      if rcpt[1] != quot;ilya@igvita.comquot;
       conn.send_data quot;550 No such user herenquot;
       data = nil
      end
    end

   data
  end

  conn.on_response do |backend, resp|
   resp
  end
                                             Defeating SMTP Wildcards
 end
                                                                        Intercepting proxy



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Proxy.start(:host => quot;0.0.0.0quot;, :port => 2524) do |conn|
  conn.server :srv, :host => quot;127.0.0.1quot;, :port => 2525

  # RCPT TO:<name@address.com>rn
  RCPT_CMD = /RCPT TO:<(.*)?>rn/

  conn.on_data do |data|
                                                              Allow: ilya@igvita.com
    if rcpt = data.match(RCPT_CMD)
      if rcpt[1] != quot;ilya@igvita.comquot;
       conn.send_data quot;550 No such user herenquot;
       data = nil                                              550 Error otherwise
      end
    end

   data
  end

  conn.on_response do |backend, resp|
   resp
  end
                                             Defeating SMTP Wildcards
 end
                                                                         Intercepting proxy



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy    @igrigorik #railsconf
[ilya@igvita] > mailtrap run –p 2525 –f /tmp/mailtrap.log
 [ilya@igvita] > ruby examples/smtp_whitelist.rb



  > require 'net/smtp‘
  > smtp = Net::SMTP.start(quot;localhostquot;, 2524)
  > smtp.send_message quot;Hello World!quot;, quot;ilya@aiderss.comquot;, quot;ilya@igvita.comquot;
  => #<Net::SMTP::Response:0xb7dcff5c @status=quot;250quot;, @string=quot;250 OKnquot;>
  > smtp.finish
  => #<Net::SMTP::Response:0xb7dcc8d4 @status=quot;221quot;, @string=quot;221 Seeyanquot;>

  > smtp.send_message quot;Hello World!quot;, quot;ilya@aiderss.comquot;, “missing_user@igvita.comquot;
  => Net::SMTPFatalError: 550 No such user here




                                         Duplex HTTP: Benchmarking
                                                                          Intercepting proxy



Ruby Proxies + EventMachine     http://bit.ly/railsconf-proxy   @igrigorik #railsconf
[ilya@igvita] > mailtrap run –p 2525 –f /tmp/mailtrap.log
 [ilya@igvita] > ruby examples/smtp_whitelist.rb


                                                                          To: ilya@igvita.com
  > require 'net/smtp‘
  > smtp = Net::SMTP.start(quot;localhostquot;, 2524)

  > smtp.send_message quot;Hello World!quot;, quot;ilya@aiderss.comquot;, quot;ilya@igvita.comquot;
  => #<Net::SMTP::Response:0xb7dcff5c @status=quot;250quot;, @string=quot;250 OKnquot;>

  > smtp.finish
  => #<Net::SMTP::Response:0xb7dcc8d4 @status=quot;221quot;, @string=quot;221 Seeyanquot;>

  > smtp.send_message quot;Hello World!quot;, quot;ilya@aiderss.comquot;, “missing_user@igvita.comquot;
  => Net::SMTPFatalError: 550 No such user here

                                                                                       Denied!


                                              Duplex HTTP: Benchmarking
                                                                               Intercepting proxy



Ruby Proxies + EventMachine          http://bit.ly/railsconf-proxy   @igrigorik #railsconf
“Hacking SMTP”.gsub(/Hacking/, ’Kung-fu’)
                                                              DIY spam filtering with Defensio




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy           @igrigorik #railsconf
Proxy.start(:host => quot;0.0.0.0quot;, :port => 2524) do |conn|
  conn.server :srv, :host => quot;127.0.0.1quot;, :port => 2525

  RCPT_CMD = /RCPT TO:<(.*)?>rn/
  FROM_CMD = /MAIL FROM:<(.*)?>rn/
  MSG_CMD = /354 Start your message/
  MSGEND_CMD = /^.rn/                                            Intercept commands

  conn.on_data do |data|
   #…
  end

  conn.on_response do |server, resp|
   p [:resp, resp]

    if resp.match(MSG_CMD)
      @buffer = true
      @msg = quot;quot;
    end

   resp
                                                         SMTP + SPAM Filtering
  end
 end
                                                               building a state-machine



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy     @igrigorik #railsconf
Proxy.start(:host => quot;0.0.0.0quot;, :port => 2524) do |conn|
  conn.server :srv, :host => quot;127.0.0.1quot;, :port => 2525

  RCPT_CMD = /RCPT TO:<(.*)?>rn/
  FROM_CMD = /MAIL FROM:<(.*)?>rn/
  MSG_CMD = /354 Start your message/
  MSGEND_CMD = /^.rn/

  conn.on_data do |data|
   #…
  end

  conn.on_response do |server, resp|
   p [:resp, resp]

    if resp.match(MSG_CMD)                                       Flag & Buffer message
      @buffer = true
      @msg = quot;quot;
    end

   resp
                                                         SMTP + SPAM Filtering
  end
 end
                                                               building a state-machine



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy     @igrigorik #railsconf
Save data

 conn.on_data do |data|
   @from = data.match(FROM_CMD)[1] if data.match(FROM_CMD)
   @rcpt = data.match(RCPT_CMD)[1] if data.match(RCPT_CMD)
   @done = true if data.match(MSGEND_CMD)

    if @buffer
      @msg += data
                                                     Buffer
      data = nil
    end

    if @done
     #…
    end

   data
                                                         SMTP + SPAM Filtering
  end
                                                               building a state-machine



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy     @igrigorik #railsconf
conn.on_data do |data|
   @from = data.match(FROM_CMD)[1] if data.match(FROM_CMD)
   @rcpt = data.match(RCPT_CMD)[1] if data.match(RCPT_CMD)
   @done = true if data.match(MSGEND_CMD)

    if @buffer
      @msg += data
                                        Flag end of message
      data = nil
    end

    if @done
     #…                                    Process message
    end

   data
                                                         SMTP + SPAM Filtering
  end
                                                               building a state-machine



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy     @igrigorik #railsconf
Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
@buffer = false
 uri = URI.parse('http://api.defensio.com/app/1.2/audit/key.yaml')
 res = Net::HTTP.post_form(uri, {
       quot;owner-urlquot; => quot;http://www.github.com/igrigorik/em-proxyquot;,
       quot;user-ipquot; => quot;216.16.254.254quot;,
       quot;article-datequot; => quot;2009/05/01quot;,
       quot;comment-authorquot; => @from,
                                                       Defensio API
       quot;comment-typequot; => quot;commentquot;,
       quot;comment-contentquot; => @msg})

      defensio = YAML.load(res.body)['defensio-result']
      p [:defensio, quot;SPAM: #{defensio['spam']}quot;]

      if defensio['spam']
        conn.send_data quot;550 No such user herenquot;
      else
        data = @msg
      end

                                                         SMTP + SPAM Filtering
                                                               building a state-machine



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy     @igrigorik #railsconf
@buffer = false
 uri = URI.parse('http://api.defensio.com/app/1.2/audit/key.yaml')
 res = Net::HTTP.post_form(uri, {
       quot;owner-urlquot; => quot;http://www.github.com/igrigorik/em-proxyquot;,
       quot;user-ipquot; => quot;216.16.254.254quot;,
       quot;article-datequot; => quot;2009/05/01quot;,
       quot;comment-authorquot; => @from,
       quot;comment-typequot; => quot;commentquot;,
       quot;comment-contentquot; => @msg})

      defensio = YAML.load(res.body)['defensio-result']
      p [:defensio, quot;SPAM: #{defensio['spam']}quot;]

      if defensio['spam']
                                                                          Pass / Deny Message
        conn.send_data quot;550 No such user herenquot;
      else
        data = @msg
      end

                                                         SMTP + SPAM Filtering
                                                               building a state-machine



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy     @igrigorik #railsconf
Protocol Trace


   [:relay_from_backend, :srv, quot;354 Start your messagequot;]
   [:resp, quot;354 Start your messagequot;]
   [:srv, quot;nquot;]
   [:relay_from_backend, :srv, quot;nquot;]
   [:resp, quot;nquot;]
   [:connection, quot;Hello Worldrnquot;]
   [:connection, quot;.rnquot;]
   [:defensio, quot;SPAM: false, Spaminess: 0.4quot;]
   [:srv, quot;250 OKnquot;]
   [:relay_from_backend, :srv, quot;250 OKnquot;]
   [:resp, quot;250 OKnquot;]




                                                         SMTP + SPAM Filtering
                                                               building a state-machine



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy     @igrigorik #railsconf
@PostRank: Beanstalkd + Ruby Proxy
                                                              because RAM is still expensive




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy         @igrigorik #railsconf
~ 93 Bytes of overhead per job
        ~300 Bytes of data / job

          x 80,000,000 jobs in memory

          ~ 30 GB of RAM = 2 X-Large EC2 instances


                 Oi, expensive!




                                                                  Beanstalkd Math



Ruby Proxies + EventMachine       http://bit.ly/railsconf-proxy    @igrigorik #railsconf
Observations:
         1. Each job is rescheduled several times
         2. > 95% are scheduled for > 3 hours into the future


                              Memory is wasted…


          3. Beanstalkd does not have overflow page-to-disk


                     We’ll add it ourselves!
                                                                      Extending Beanstalkd



Ruby Proxies + EventMachine           http://bit.ly/railsconf-proxy        @igrigorik #railsconf
1 “Medium” EC2 Instance
                       Intercepting Proxy



                                                                         MySQL
                                         EM-Proxy




                                                                        Beanstalkd




                                  @PostRank: “Chronos Scheduler”


Ruby Proxies + EventMachine          http://bit.ly/railsconf-proxy      @igrigorik #railsconf
Proxy.start(:host => quot;0.0.0.0quot;, :port => 11300) do |conn|
  conn.server :srv, :host => quot;127.0.0.1quot;, :port => 11301
  PUT_CMD = /put (d+) (d+) (d+) (d+)rn/

  conn.on_data do |data|
   if put = data.match(PUT_CMD)                                  Intercept PUT command
     if put[2].to_i > 600
       p [:put, :archive]
       # INSERT INTO ....
       conn.send_data quot;INSERTED 9999rnquot;
       data = nil
     end
    end

   data
  end

  conn.on_response do |backend, resp|
   resp
  end
 end




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy   @igrigorik #railsconf
Proxy.start(:host => quot;0.0.0.0quot;, :port => 11300) do |conn|
  conn.server :srv, :host => quot;127.0.0.1quot;, :port => 11301
  PUT_CMD = /put (d+) (d+) (d+) (d+)rn/

  conn.on_data do |data|
   if put = data.match(PUT_CMD)

      if put[2].to_i > 600                                    If over 10 minutes…
        p [:put, :archive]
        # INSERT INTO ....

      conn.send_data quot;INSERTED 9999rnquot;
      data = nil
     end
    end                                                        Archive & Reply

   data
  end

  conn.on_response do |backend, resp|
   resp
  end
 end



Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy     @igrigorik #railsconf
Overload the protocol



                                                                       MySQL
                                    EM-Proxy


                                                                PUT




                                           RESERVE, PUT, …
        put job, 900
                                                                      Beanstalkd




                              @PostRank: “Chronos Scheduler”


Ruby Proxies + EventMachine     http://bit.ly/railsconf-proxy         @igrigorik #railsconf
400% cheaper + extensible!                  ~79,000,000 jobs, 4GB RAM



                                                                          MySQL
                                       EM-Proxy


                                                                   PUT



     Upcoming jobs: ~ 1M
                                              RESERVE, PUT, …
                                                                         Beanstalkd




                              @PostRank: “Chronos Scheduler”


Ruby Proxies + EventMachine        http://bit.ly/railsconf-proxy         @igrigorik #railsconf
%w[ Transparent <Intercepting> Caching … +
                                                              solution for every problem




Ruby Proxies + EventMachine   http://bit.ly/railsconf-proxy     @igrigorik #railsconf
Slides: http://bit.ly/railsconf-proxy
    Code: http://github.com/igrigorik/em-proxy

    Twitter: @igrigorik




                                                             Thanks. Questions?

                              The slides…                         Twitter                           My blog


Ruby Proxies + EventMachine       http://bit.ly/railsconf-proxy             @igrigorik #railsconf

Mais conteúdo relacionado

Mais procurados

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
 
Building WebSocket and Server Side Events Applications using Atmosphere
Building WebSocket and Server Side Events Applications using AtmosphereBuilding WebSocket and Server Side Events Applications using Atmosphere
Building WebSocket and Server Side Events Applications using Atmospherejfarcand
 
Ruby 1.9 Fibers
Ruby 1.9 FibersRuby 1.9 Fibers
Ruby 1.9 FibersKevin Ball
 
Ruby vs Node ShiningRay Shanghai
Ruby vs Node ShiningRay ShanghaiRuby vs Node ShiningRay Shanghai
Ruby vs Node ShiningRay ShanghaiJackson Tian
 
No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010Ilya Grigorik
 
Scaling Ruby with Evented I/O - Ruby underground
Scaling Ruby with Evented I/O - Ruby undergroundScaling Ruby with Evented I/O - Ruby underground
Scaling Ruby with Evented I/O - Ruby undergroundOmer Gazit
 
Writing Portable WebSockets in Java
Writing Portable WebSockets in JavaWriting Portable WebSockets in Java
Writing Portable WebSockets in Javajfarcand
 
Solving some of the scalability problems at booking.com
Solving some of the scalability problems at booking.comSolving some of the scalability problems at booking.com
Solving some of the scalability problems at booking.comIvan Kruglov
 
Why async matters
Why async mattersWhy async matters
Why async matterstimbc
 
Smart Gamma - Real-Time Web applications with PHP and Websocket.
Smart Gamma - Real-Time Web applications with PHP and Websocket.Smart Gamma - Real-Time Web applications with PHP and Websocket.
Smart Gamma - Real-Time Web applications with PHP and Websocket.Evgeniy Kuzmin
 
20141210 rakuten techtalk
20141210 rakuten techtalk20141210 rakuten techtalk
20141210 rakuten techtalkHiroshi SHIBATA
 
Gearman - Job Queue
Gearman - Job QueueGearman - Job Queue
Gearman - Job QueueDiego Lewin
 
WebSockets wiith Scala and Play! Framework
WebSockets wiith Scala and Play! FrameworkWebSockets wiith Scala and Play! Framework
WebSockets wiith Scala and Play! FrameworkFabio Tiriticco
 
The details of CI/CD environment for Ruby
The details of CI/CD environment for RubyThe details of CI/CD environment for Ruby
The details of CI/CD environment for RubyHiroshi SHIBATA
 
So you think JSON is cool?
So you think JSON is cool?So you think JSON is cool?
So you think JSON is cool?Herval Freire
 
Faster PHP apps using Queues and Workers
Faster PHP apps using Queues and WorkersFaster PHP apps using Queues and Workers
Faster PHP apps using Queues and WorkersRichard Baker
 

Mais procurados (19)

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
 
Concurrency in ruby
Concurrency in rubyConcurrency in ruby
Concurrency in ruby
 
Building WebSocket and Server Side Events Applications using Atmosphere
Building WebSocket and Server Side Events Applications using AtmosphereBuilding WebSocket and Server Side Events Applications using Atmosphere
Building WebSocket and Server Side Events Applications using Atmosphere
 
Ruby 1.9 Fibers
Ruby 1.9 FibersRuby 1.9 Fibers
Ruby 1.9 Fibers
 
Ruby vs Node ShiningRay Shanghai
Ruby vs Node ShiningRay ShanghaiRuby vs Node ShiningRay Shanghai
Ruby vs Node ShiningRay Shanghai
 
No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010
 
Scaling Ruby with Evented I/O - Ruby underground
Scaling Ruby with Evented I/O - Ruby undergroundScaling Ruby with Evented I/O - Ruby underground
Scaling Ruby with Evented I/O - Ruby underground
 
Grape golilath
Grape golilathGrape golilath
Grape golilath
 
Writing Portable WebSockets in Java
Writing Portable WebSockets in JavaWriting Portable WebSockets in Java
Writing Portable WebSockets in Java
 
Speedy TDD with Rails
Speedy TDD with RailsSpeedy TDD with Rails
Speedy TDD with Rails
 
Solving some of the scalability problems at booking.com
Solving some of the scalability problems at booking.comSolving some of the scalability problems at booking.com
Solving some of the scalability problems at booking.com
 
Why async matters
Why async mattersWhy async matters
Why async matters
 
Smart Gamma - Real-Time Web applications with PHP and Websocket.
Smart Gamma - Real-Time Web applications with PHP and Websocket.Smart Gamma - Real-Time Web applications with PHP and Websocket.
Smart Gamma - Real-Time Web applications with PHP and Websocket.
 
20141210 rakuten techtalk
20141210 rakuten techtalk20141210 rakuten techtalk
20141210 rakuten techtalk
 
Gearman - Job Queue
Gearman - Job QueueGearman - Job Queue
Gearman - Job Queue
 
WebSockets wiith Scala and Play! Framework
WebSockets wiith Scala and Play! FrameworkWebSockets wiith Scala and Play! Framework
WebSockets wiith Scala and Play! Framework
 
The details of CI/CD environment for Ruby
The details of CI/CD environment for RubyThe details of CI/CD environment for Ruby
The details of CI/CD environment for Ruby
 
So you think JSON is cool?
So you think JSON is cool?So you think JSON is cool?
So you think JSON is cool?
 
Faster PHP apps using Queues and Workers
Faster PHP apps using Queues and WorkersFaster PHP apps using Queues and Workers
Faster PHP apps using Queues and Workers
 

Semelhante a Ruby Proxies for Scale, Performance, and Monitoring

When Two Worlds Collide: Java and Ruby in the Enterprise
When Two Worlds Collide: Java and Ruby in the EnterpriseWhen Two Worlds Collide: Java and Ruby in the Enterprise
When Two Worlds Collide: Java and Ruby in the Enterprisebenbrowning
 
[2011-17-C-4] Heroku & database.com
[2011-17-C-4] Heroku & database.com[2011-17-C-4] Heroku & database.com
[2011-17-C-4] Heroku & database.comMitch Okamoto
 
State of Developer Tools (WDS09)
State of Developer Tools (WDS09)State of Developer Tools (WDS09)
State of Developer Tools (WDS09)bgalbs
 
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011leo lapworth
 
Foreman - Process manager for applications with multiple components
Foreman - Process manager for applications with multiple componentsForeman - Process manager for applications with multiple components
Foreman - Process manager for applications with multiple componentsStoyan Zhekov
 
Everyday tools and tricks for scaling Node.js
Everyday tools and tricks for scaling Node.jsEveryday tools and tricks for scaling Node.js
Everyday tools and tricks for scaling Node.jsNikolay Stoitsev
 
Toster - Understanding the Rails Web Model and Scalability Options
Toster - Understanding the Rails Web Model and Scalability OptionsToster - Understanding the Rails Web Model and Scalability Options
Toster - Understanding the Rails Web Model and Scalability OptionsFabio Akita
 
Understanding the Rails web model and scalability options
Understanding the Rails web model and scalability optionsUnderstanding the Rails web model and scalability options
Understanding the Rails web model and scalability options.toster
 
Wakanda: NoSQL & SSJS for Model-driven Web Applications - SourceDevCon 2012
Wakanda: NoSQL & SSJS for Model-driven Web Applications - SourceDevCon 2012Wakanda: NoSQL & SSJS for Model-driven Web Applications - SourceDevCon 2012
Wakanda: NoSQL & SSJS for Model-driven Web Applications - SourceDevCon 2012Alexandre Morgaut
 
ECS19 - Damir Dobric - Designing and Operating modern applications with Micro...
ECS19 - Damir Dobric - Designing and Operating modern applications with Micro...ECS19 - Damir Dobric - Designing and Operating modern applications with Micro...
ECS19 - Damir Dobric - Designing and Operating modern applications with Micro...European Collaboration Summit
 
JRuby At LinkedIn
JRuby At LinkedInJRuby At LinkedIn
JRuby At LinkedInbaqhaidri
 

Semelhante a Ruby Proxies for Scale, Performance, and Monitoring (20)

When Two Worlds Collide: Java and Ruby in the Enterprise
When Two Worlds Collide: Java and Ruby in the EnterpriseWhen Two Worlds Collide: Java and Ruby in the Enterprise
When Two Worlds Collide: Java and Ruby in the Enterprise
 
Cucumber
CucumberCucumber
Cucumber
 
[2011-17-C-4] Heroku & database.com
[2011-17-C-4] Heroku & database.com[2011-17-C-4] Heroku & database.com
[2011-17-C-4] Heroku & database.com
 
State of Developer Tools (WDS09)
State of Developer Tools (WDS09)State of Developer Tools (WDS09)
State of Developer Tools (WDS09)
 
Ruby On Rails
Ruby On RailsRuby On Rails
Ruby On Rails
 
Where is my scalable API?
Where is my scalable API?Where is my scalable API?
Where is my scalable API?
 
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
 
Foreman - Process manager for applications with multiple components
Foreman - Process manager for applications with multiple componentsForeman - Process manager for applications with multiple components
Foreman - Process manager for applications with multiple components
 
RubyConf Brazil 2011
RubyConf Brazil 2011RubyConf Brazil 2011
RubyConf Brazil 2011
 
Project Zero Php Quebec
Project Zero Php QuebecProject Zero Php Quebec
Project Zero Php Quebec
 
Web application intro
Web application introWeb application intro
Web application intro
 
COMET in Plone
COMET in PloneCOMET in Plone
COMET in Plone
 
Everyday tools and tricks for scaling Node.js
Everyday tools and tricks for scaling Node.jsEveryday tools and tricks for scaling Node.js
Everyday tools and tricks for scaling Node.js
 
Toster - Understanding the Rails Web Model and Scalability Options
Toster - Understanding the Rails Web Model and Scalability OptionsToster - Understanding the Rails Web Model and Scalability Options
Toster - Understanding the Rails Web Model and Scalability Options
 
Understanding the Rails web model and scalability options
Understanding the Rails web model and scalability optionsUnderstanding the Rails web model and scalability options
Understanding the Rails web model and scalability options
 
Project Zero JavaOne 2008
Project Zero JavaOne 2008Project Zero JavaOne 2008
Project Zero JavaOne 2008
 
Wakanda: NoSQL & SSJS for Model-driven Web Applications - SourceDevCon 2012
Wakanda: NoSQL & SSJS for Model-driven Web Applications - SourceDevCon 2012Wakanda: NoSQL & SSJS for Model-driven Web Applications - SourceDevCon 2012
Wakanda: NoSQL & SSJS for Model-driven Web Applications - SourceDevCon 2012
 
ECS19 - Damir Dobric - Designing and Operating modern applications with Micro...
ECS19 - Damir Dobric - Designing and Operating modern applications with Micro...ECS19 - Damir Dobric - Designing and Operating modern applications with Micro...
ECS19 - Damir Dobric - Designing and Operating modern applications with Micro...
 
Guides To Analyzing WebKit Performance
Guides To Analyzing WebKit PerformanceGuides To Analyzing WebKit Performance
Guides To Analyzing WebKit Performance
 
JRuby At LinkedIn
JRuby At LinkedInJRuby At LinkedIn
JRuby At LinkedIn
 

Mais de 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
 
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
 

Mais de Ilya Grigorik (9)

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
 
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
 

Último

UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7DianaGray10
 
PicPay - GenAI Finance Assistant - ChatGPT for Customer Service
PicPay - GenAI Finance Assistant - ChatGPT for Customer ServicePicPay - GenAI Finance Assistant - ChatGPT for Customer Service
PicPay - GenAI Finance Assistant - ChatGPT for Customer ServiceRenan Moreira de Oliveira
 
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
 
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
 
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
 
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
 
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
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Commit University
 
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationUsing IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationIES VE
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...DianaGray10
 
Bird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemBird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemAsko Soukka
 
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
 
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
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesDavid Newbury
 
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
 
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
 
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
 
Introduction to Quantum Computing
Introduction to Quantum ComputingIntroduction to Quantum Computing
Introduction to Quantum ComputingGDSC PJATK
 
Babel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptxBabel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptxYounusS2
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8DianaGray10
 

Último (20)

UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7
 
PicPay - GenAI Finance Assistant - ChatGPT for Customer Service
PicPay - GenAI Finance Assistant - ChatGPT for Customer ServicePicPay - GenAI Finance Assistant - ChatGPT for Customer Service
PicPay - GenAI Finance Assistant - ChatGPT for Customer Service
 
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
 
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
 
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
 
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
 
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
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
 
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationUsing IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
 
Bird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemBird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystem
 
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
 
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?
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond Ontologies
 
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
 
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
 
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
 
Introduction to Quantum Computing
Introduction to Quantum ComputingIntroduction to Quantum Computing
Introduction to Quantum Computing
 
Babel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptxBabel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptx
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8
 

Ruby Proxies for Scale, Performance, and Monitoring

  • 1. Ruby Proxies for Scale, Performance and Monitoring Ilya Grigorik @igrigorik Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 2. postrank.com/topic/ruby The slides… Twitter My blog Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 3. Code + Examples EventMachine Misc Proxies Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 4. Proxy Love Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 5. “Rails, Django, Seaside, Grails…” cant scale. Myth: Slow Frameworks Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 6. The Proxy Solution Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 7. The “More” Proxy Solution Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 8. Transparent Scalability Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 9. Load Balancer Reverse Proxy App Server MySQL Proxy Proxy as Middleware middleware ftw! Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 10. 90% use case %w*Transparent Intercepting Caching …+ There are many different types! Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 11. Transparent HAProxy App server A App server B Transparent, Cut-Through Proxy Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 12. Transparent Proxy = Scalability Power Tool Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 13. Proxy Proxy App server A App server B App server C Problem: Staging Environment Production Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 14. Simulating traffic? Proxy Duplication App server C “Representative Load / Staging” Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 15. github.com/igrigorik/autoperf Replay log data, rinse, repeat Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 16. Profile of queries has changed Fail Load on production has changed Fail Parallel environment Fail Slower release cycle Fail Staging fail. Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 17. Duplex Ruby Proxy, FTW! Production Real (production) traffic Benchmark Benchmarking Proxy flash of the obvious Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 18. github.com/igrigorik/em-proxy Proxy DSL FTW! Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 19. EventMachine: Speed + Convenience building high performance network apps in Ruby Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 20. p quot;Startingquot; while true do EM.run do timers p quot;Running in EM reactorquot; network_io end other_io end puts quot;Almost donequot; EventMachine Reactor concurrency without threads Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 21. p quot;Startingquot; while true do EM.run do timers p quot;Running in EM reactorquot; network_io end other_io end puts quot;Almost donequot; EventMachine Reactor concurrency without threads Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 22. C++ core Easy concurrency without threading EventMachine Reactor concurrency without threads Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 23. http = EM::HttpRequest.new('http://site.com/').get http.callback { p http.response } # ... do other work, until callback fires. Event = IO event + block or lambda call EventMachine Reactor concurrency without threads Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 24. http = EM::HttpRequest.new('http://site.com/').get http.callback { p http.response } # ... do other work, until callback fires. Event = IO event + block or lambda call EventMachine Reactor concurrency without threads Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 25. EM.run do EM.add_timer(1) { p quot;1 second laterquot; } EM.add_periodic_timer(5) { p quot;every 5 secondsquot;} EM.defer { long_running_task() } end class Server < EM::Connection def receive_data(data) send_data(quot;Pong; #{data}quot;) end def unbind p [:connection_completed] end end EM.run do EM.start_server quot;0.0.0.0quot;, 3000, Server end Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 26. EM.run do EM.add_timer(1) { p quot;1 second laterquot; } EM.add_periodic_timer(5) { p quot;every 5 secondsquot;} EM.defer { long_running_task() } end class Server < EM::Connection def receive_data(data) send_data(quot;Pong; #{data}quot;) Connection Handler end def unbind p [:connection_completed] end end EM.run do Start Reactor EM.start_server quot;0.0.0.0quot;, 3000, Server end Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 27. http://bit.ly/aiderss-eventmachine by Dan Sinclair (Twitter: @dj2sincl) Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 28. Proxies for Monitoring, Performance and Scale welcome to the wonderful world of… Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 29. Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn| conn.server :name, :host => quot;127.0.0.1quot;, :port => 81 conn.on_data do |data| # ... end Relay Server conn.on_response do |server, resp| # ... end conn.on_finish do # ... end end EM-Proxy www.github.com/igrigorik/em-proxy Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 30. Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn| conn.server :name, :host => quot;127.0.0.1quot;, :port => 81 conn.on_data do |data| # ... end Process incoming data conn.on_response do |server, resp| # ... end conn.on_finish do # ... end end EM-Proxy www.github.com/igrigorik/em-proxy Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 31. Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn| conn.server :name, :host => quot;127.0.0.1quot;, :port => 81 conn.on_data do |data| # ... end Process response data conn.on_response do |server, resp| # ... end conn.on_finish do # ... end end EM-Proxy www.github.com/igrigorik/em-proxy Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 32. Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn| conn.server :name, :host => quot;127.0.0.1quot;, :port => 81 conn.on_data do |data| # ... end conn.on_response do |server, resp| # ... end Post-processing step conn.on_finish do # ... end end EM-Proxy www.github.com/igrigorik/em-proxy Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 33. %w[ <Transparent> Intercepting Caching … + solution for every problem Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 34. Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn| conn.server :srv, :host => quot;127.0.0.1quot;, :port => 81 # modify / process request stream conn.on_data do |data| p [:on_data, data] data end No data modifications # modify / process response stream conn.on_response do |server, resp| p [:on_response, server, resp] resp end end Port-Forwarding transparent proxy Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 35. Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn| conn.server :srv, :host => quot;127.0.0.1quot;, :port => 81 conn.on_data do |data| data end conn.on_response do |backend, resp| Alter response resp.gsub(/hello/, 'good bye') end end Port-Forwarding + Alter transparent proxy Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 36. %w[ Transparent <Intercepting> Caching … + solution for every problem Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 37. Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn| @start = Time.now @data = Hash.new(quot;quot;) Prod + Test conn.server :prod, :host => quot;127.0.0.1quot;, :port => 81 conn.server :test, :host => quot;127.0.0.1quot;, :port => 82 conn.on_data do |data| data.gsub(/User-Agent: .*?rn/, 'User-Agent: em-proxyrn') end conn.on_response do |server, resp| @data[server] += resp resp if server == :prod end conn.on_finish do p [:on_finish, Time.now - @start] p @data end end Duplex HTTP: Benchmarking Intercepting proxy Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 38. Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn| @start = Time.now @data = Hash.new(quot;quot;) conn.server :prod, :host => quot;127.0.0.1quot;, :port => 81 conn.server :test, :host => quot;127.0.0.1quot;, :port => 82 conn.on_data do |data| data.gsub(/User-Agent: .*?rn/, 'User-Agent: em-proxyrn') end conn.on_response do |server, resp| Respond from production @data[server] += resp resp if server == :prod end conn.on_finish do p [:on_finish, Time.now - @start] p @data end end Duplex HTTP: Benchmarking Intercepting proxy Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 39. Proxy.start(:host => quot;0.0.0.0quot;, :port => 80) do |conn| @start = Time.now @data = Hash.new(quot;quot;) conn.server :prod, :host => quot;127.0.0.1quot;, :port => 81 conn.server :test, :host => quot;127.0.0.1quot;, :port => 82 conn.on_data do |data| data.gsub(/User-Agent: .*?rn/, 'User-Agent: em-proxyrn') end conn.on_response do |server, resp| @data[server] += resp resp if server == :prod end Run post-processing conn.on_finish do p [:on_finish, Time.now - @start] p @data end end Duplex HTTP: Benchmarking Intercepting proxy Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 40. [ilya@igvita] > ruby examples/appserver.rb 81 [ilya@igvita] > ruby examples/appserver.rb 82 [ilya@igvita] > ruby examples/line_interceptor.rb [ilya@igvita] > curl localhost >> [:on_finish, 1.008561] >> {:prod=>quot;HTTP/1.1 200 OKrnConnection: closernDate: Fri, 01 May 2009 04:20:00 GMTrnContent-Type: text/plainrnrnhello world: 0quot;, :test=>quot;HTTP/1.1 200 OKrnConnection: closernDate: Fri, 01 May 2009 04:20:00 GMTrnContent-Type: text/plainrnrnhello world: 1quot;} Duplex HTTP: Benchmarking Intercepting proxy Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 41. [ilya@igvita] > ruby examples/appserver.rb 81 [ilya@igvita] > ruby examples/appserver.rb 82 [ilya@igvita] > ruby examples/line_interceptor.rb [ilya@igvita] > curl localhost STDOUT [:on_finish, 1.008561] {:prod=>quot;HTTP/1.1 200 OKrnConnection: closernDate: Fri, 01 May 2009 04:20:00 GMTrnContent-Type: text/plainrnrnhello world: 0quot;, :test=>quot;HTTP/1.1 200 OKrnConnection: closernDate: Fri, 01 May 2009 04:20:00 GMTrnContent-Type: text/plainrnrnhello world: 1quot;} Duplex HTTP: Benchmarking Intercepting proxy Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 42. Same response, different turnaround time Different response body! Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 43. Woops! Validating Proxy easy, real-time diagnostics Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 44. Hacking SMTP for fun and profit Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 45. Proxy.start(:host => quot;0.0.0.0quot;, :port => 2524) do |conn| conn.server :srv, :host => quot;127.0.0.1quot;, :port => 2525 # RCPT TO:<name@address.com>rn RCPT_CMD = /RCPT TO:<(.*)?>rn/ Intercept Addressee conn.on_data do |data| if rcpt = data.match(RCPT_CMD) if rcpt[1] != quot;ilya@igvita.comquot; conn.send_data quot;550 No such user herenquot; data = nil end end data end conn.on_response do |backend, resp| resp end Defeating SMTP Wildcards end Intercepting proxy Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 46. Proxy.start(:host => quot;0.0.0.0quot;, :port => 2524) do |conn| conn.server :srv, :host => quot;127.0.0.1quot;, :port => 2525 # RCPT TO:<name@address.com>rn RCPT_CMD = /RCPT TO:<(.*)?>rn/ conn.on_data do |data| Allow: ilya@igvita.com if rcpt = data.match(RCPT_CMD) if rcpt[1] != quot;ilya@igvita.comquot; conn.send_data quot;550 No such user herenquot; data = nil 550 Error otherwise end end data end conn.on_response do |backend, resp| resp end Defeating SMTP Wildcards end Intercepting proxy Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 47. [ilya@igvita] > mailtrap run –p 2525 –f /tmp/mailtrap.log [ilya@igvita] > ruby examples/smtp_whitelist.rb > require 'net/smtp‘ > smtp = Net::SMTP.start(quot;localhostquot;, 2524) > smtp.send_message quot;Hello World!quot;, quot;ilya@aiderss.comquot;, quot;ilya@igvita.comquot; => #<Net::SMTP::Response:0xb7dcff5c @status=quot;250quot;, @string=quot;250 OKnquot;> > smtp.finish => #<Net::SMTP::Response:0xb7dcc8d4 @status=quot;221quot;, @string=quot;221 Seeyanquot;> > smtp.send_message quot;Hello World!quot;, quot;ilya@aiderss.comquot;, “missing_user@igvita.comquot; => Net::SMTPFatalError: 550 No such user here Duplex HTTP: Benchmarking Intercepting proxy Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 48. [ilya@igvita] > mailtrap run –p 2525 –f /tmp/mailtrap.log [ilya@igvita] > ruby examples/smtp_whitelist.rb To: ilya@igvita.com > require 'net/smtp‘ > smtp = Net::SMTP.start(quot;localhostquot;, 2524) > smtp.send_message quot;Hello World!quot;, quot;ilya@aiderss.comquot;, quot;ilya@igvita.comquot; => #<Net::SMTP::Response:0xb7dcff5c @status=quot;250quot;, @string=quot;250 OKnquot;> > smtp.finish => #<Net::SMTP::Response:0xb7dcc8d4 @status=quot;221quot;, @string=quot;221 Seeyanquot;> > smtp.send_message quot;Hello World!quot;, quot;ilya@aiderss.comquot;, “missing_user@igvita.comquot; => Net::SMTPFatalError: 550 No such user here Denied! Duplex HTTP: Benchmarking Intercepting proxy Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 49. “Hacking SMTP”.gsub(/Hacking/, ’Kung-fu’) DIY spam filtering with Defensio Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 50. Proxy.start(:host => quot;0.0.0.0quot;, :port => 2524) do |conn| conn.server :srv, :host => quot;127.0.0.1quot;, :port => 2525 RCPT_CMD = /RCPT TO:<(.*)?>rn/ FROM_CMD = /MAIL FROM:<(.*)?>rn/ MSG_CMD = /354 Start your message/ MSGEND_CMD = /^.rn/ Intercept commands conn.on_data do |data| #… end conn.on_response do |server, resp| p [:resp, resp] if resp.match(MSG_CMD) @buffer = true @msg = quot;quot; end resp SMTP + SPAM Filtering end end building a state-machine Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 51. Proxy.start(:host => quot;0.0.0.0quot;, :port => 2524) do |conn| conn.server :srv, :host => quot;127.0.0.1quot;, :port => 2525 RCPT_CMD = /RCPT TO:<(.*)?>rn/ FROM_CMD = /MAIL FROM:<(.*)?>rn/ MSG_CMD = /354 Start your message/ MSGEND_CMD = /^.rn/ conn.on_data do |data| #… end conn.on_response do |server, resp| p [:resp, resp] if resp.match(MSG_CMD) Flag & Buffer message @buffer = true @msg = quot;quot; end resp SMTP + SPAM Filtering end end building a state-machine Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 52. Save data conn.on_data do |data| @from = data.match(FROM_CMD)[1] if data.match(FROM_CMD) @rcpt = data.match(RCPT_CMD)[1] if data.match(RCPT_CMD) @done = true if data.match(MSGEND_CMD) if @buffer @msg += data Buffer data = nil end if @done #… end data SMTP + SPAM Filtering end building a state-machine Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 53. conn.on_data do |data| @from = data.match(FROM_CMD)[1] if data.match(FROM_CMD) @rcpt = data.match(RCPT_CMD)[1] if data.match(RCPT_CMD) @done = true if data.match(MSGEND_CMD) if @buffer @msg += data Flag end of message data = nil end if @done #… Process message end data SMTP + SPAM Filtering end building a state-machine Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 54. Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 55. @buffer = false uri = URI.parse('http://api.defensio.com/app/1.2/audit/key.yaml') res = Net::HTTP.post_form(uri, { quot;owner-urlquot; => quot;http://www.github.com/igrigorik/em-proxyquot;, quot;user-ipquot; => quot;216.16.254.254quot;, quot;article-datequot; => quot;2009/05/01quot;, quot;comment-authorquot; => @from, Defensio API quot;comment-typequot; => quot;commentquot;, quot;comment-contentquot; => @msg}) defensio = YAML.load(res.body)['defensio-result'] p [:defensio, quot;SPAM: #{defensio['spam']}quot;] if defensio['spam'] conn.send_data quot;550 No such user herenquot; else data = @msg end SMTP + SPAM Filtering building a state-machine Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 56. @buffer = false uri = URI.parse('http://api.defensio.com/app/1.2/audit/key.yaml') res = Net::HTTP.post_form(uri, { quot;owner-urlquot; => quot;http://www.github.com/igrigorik/em-proxyquot;, quot;user-ipquot; => quot;216.16.254.254quot;, quot;article-datequot; => quot;2009/05/01quot;, quot;comment-authorquot; => @from, quot;comment-typequot; => quot;commentquot;, quot;comment-contentquot; => @msg}) defensio = YAML.load(res.body)['defensio-result'] p [:defensio, quot;SPAM: #{defensio['spam']}quot;] if defensio['spam'] Pass / Deny Message conn.send_data quot;550 No such user herenquot; else data = @msg end SMTP + SPAM Filtering building a state-machine Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 57. Protocol Trace [:relay_from_backend, :srv, quot;354 Start your messagequot;] [:resp, quot;354 Start your messagequot;] [:srv, quot;nquot;] [:relay_from_backend, :srv, quot;nquot;] [:resp, quot;nquot;] [:connection, quot;Hello Worldrnquot;] [:connection, quot;.rnquot;] [:defensio, quot;SPAM: false, Spaminess: 0.4quot;] [:srv, quot;250 OKnquot;] [:relay_from_backend, :srv, quot;250 OKnquot;] [:resp, quot;250 OKnquot;] SMTP + SPAM Filtering building a state-machine Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 58. @PostRank: Beanstalkd + Ruby Proxy because RAM is still expensive Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 59. ~ 93 Bytes of overhead per job ~300 Bytes of data / job x 80,000,000 jobs in memory ~ 30 GB of RAM = 2 X-Large EC2 instances Oi, expensive! Beanstalkd Math Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 60. Observations: 1. Each job is rescheduled several times 2. > 95% are scheduled for > 3 hours into the future Memory is wasted… 3. Beanstalkd does not have overflow page-to-disk We’ll add it ourselves! Extending Beanstalkd Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 61. 1 “Medium” EC2 Instance Intercepting Proxy MySQL EM-Proxy Beanstalkd @PostRank: “Chronos Scheduler” Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 62. Proxy.start(:host => quot;0.0.0.0quot;, :port => 11300) do |conn| conn.server :srv, :host => quot;127.0.0.1quot;, :port => 11301 PUT_CMD = /put (d+) (d+) (d+) (d+)rn/ conn.on_data do |data| if put = data.match(PUT_CMD) Intercept PUT command if put[2].to_i > 600 p [:put, :archive] # INSERT INTO .... conn.send_data quot;INSERTED 9999rnquot; data = nil end end data end conn.on_response do |backend, resp| resp end end Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 63. Proxy.start(:host => quot;0.0.0.0quot;, :port => 11300) do |conn| conn.server :srv, :host => quot;127.0.0.1quot;, :port => 11301 PUT_CMD = /put (d+) (d+) (d+) (d+)rn/ conn.on_data do |data| if put = data.match(PUT_CMD) if put[2].to_i > 600 If over 10 minutes… p [:put, :archive] # INSERT INTO .... conn.send_data quot;INSERTED 9999rnquot; data = nil end end Archive & Reply data end conn.on_response do |backend, resp| resp end end Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 64. Overload the protocol MySQL EM-Proxy PUT RESERVE, PUT, … put job, 900 Beanstalkd @PostRank: “Chronos Scheduler” Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 65. 400% cheaper + extensible! ~79,000,000 jobs, 4GB RAM MySQL EM-Proxy PUT Upcoming jobs: ~ 1M RESERVE, PUT, … Beanstalkd @PostRank: “Chronos Scheduler” Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 66. %w[ Transparent <Intercepting> Caching … + solution for every problem Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf
  • 67. Slides: http://bit.ly/railsconf-proxy Code: http://github.com/igrigorik/em-proxy Twitter: @igrigorik Thanks. Questions? The slides… Twitter My blog Ruby Proxies + EventMachine http://bit.ly/railsconf-proxy @igrigorik #railsconf