Rack Presentation Oct 07

  • Upload
    zh

  • View
    219

  • Download
    0

Embed Size (px)

Citation preview

  • 8/14/2019 Rack Presentation Oct 07

    1/36

    rackrolling your own, tiny like, web thingoespresentation by ryan allen - yeahnah.org (and etc)

  • 8/14/2019 Rack Presentation Oct 07

    2/36

    the problem?

    each framework has to write its ownhandlers to mongrel, webrick, fast-cgi

    duplication among frameworks, lachie killskittens

    new frameworks are required to writeeven more duplicate code, boring!

  • 8/14/2019 Rack Presentation Oct 07

    3/36

    a solution - rack

    super simple API for writing web apps

    single API to connect to mongrel, fast-cgi,webrick

    based on pythons WSGI, which was a goodthing for python

  • 8/14/2019 Rack Presentation Oct 07

    4/36

    the api

    can be satisfied with a lambda

    really, no, im serious

  • 8/14/2019 Rack Presentation Oct 07

    5/36

    lambda { |env| [200, {}, Hello World! }

  • 8/14/2019 Rack Presentation Oct 07

    6/36

    the api, cont. an object that responds to call and

    accepts one argument:env, and returns:

    a status, i.e.200 the headers, i.e.{Content-Type =>text/html}

    an object that responds to

    each, i.e.

    some random string

  • 8/14/2019 Rack Presentation Oct 07

    7/36

    this env thing

    a hash of environment variables, things likePATH_INFO,QUERY_STRING,REMOTE_ADDR,REQUEST_URI, all that

    junk

  • 8/14/2019 Rack Presentation Oct 07

    8/36

    things do to with env

    use Rack::Request to construct arequest object, pull out GET and POSTdata

    Rack borrows code from Camping, Railsand IOWA in this department

  • 8/14/2019 Rack Presentation Oct 07

    9/36

    request = Rack::Request.new(env)

    request.GETrequest.POST

  • 8/14/2019 Rack Presentation Oct 07

    10/36

    talking back, eloquently

    use Rack::Response to talk to clientsabout cookies

    additionally, you can use this instead of the[200, {}, ] return value, see:

  • 8/14/2019 Rack Presentation Oct 07

    11/36

    response = Rack::Response.new('Hello World!')

    response.set_cookie('sess-id', 'abcde')response.finish

  • 8/14/2019 Rack Presentation Oct 07

    12/36

    lots of love to mongrel

    we love mongrel to bits

    despite the fact we can plug into webrickand fast-cgi we really just love mongrel

    poor webrick and fast-cgi :(

  • 8/14/2019 Rack Presentation Oct 07

    13/36

    %w(rubygems rack).each { |dep| require dep }

    app = lambda { |env| [200, {}, 'Hello World!'] }Rack::Handler::Mongrel.run(app, :Port => 3000)

  • 8/14/2019 Rack Presentation Oct 07

    14/36

    oh, and that was acom lete rack a

  • 8/14/2019 Rack Presentation Oct 07

    15/36

    run it, it works, really!

  • 8/14/2019 Rack Presentation Oct 07

    16/36

    %w(rubygems rack).each { |dep| require dep }

    app = lambda { |env| [200, {}, 'Hello World!'] }Rack::Handler::Mongrel.run(app, :Port => 3000)

  • 8/14/2019 Rack Presentation Oct 07

    17/36

    concurrency galore

    using the mongrel handler we can get crazyconcurrency

    lets have a look at this, using ab

  • 8/14/2019 Rack Presentation Oct 07

    18/36

    %w(rubygems rack).each { |dep| require dep }

    app = lambda { |env| sleep(5); [200, {}, 'Oi!'] }Rack::Handler::Mongrel.run(app, :Port => 3000)

  • 8/14/2019 Rack Presentation Oct 07

    19/36

    ab -c 100 -n 300 http://0.0.0.0:3000/

  • 8/14/2019 Rack Presentation Oct 07

    20/36

    Benchmarking 0.0.0.0 (be patient)Completed 100 requestsCompleted 200 requestsFinished 300 requestsConcurrency Level: 100Time taken for tests: 15.232 secondsComplete requests: 300Failed requests: 0

  • 8/14/2019 Rack Presentation Oct 07

    21/36

    so?

    good like camping - very minimal, single fileapplications

    but better because camping isnt multi-threaded, requests are wrapped in a mutex

    like rails, boo!

  • 8/14/2019 Rack Presentation Oct 07

    22/36

    so??

    good like merb - multithreaded, non-blocking requests

    but better (in some scenarios) beacusemerb is a big framework mirroring a lot of

    what rails does

  • 8/14/2019 Rack Presentation Oct 07

    23/36

    so???

    people use merb to write non-blockinguploader applications to compliment rails

    applications

    but, why arent they using rack instead?

    rack is smaller, more lightweight and supereasy to write and deploy!

  • 8/14/2019 Rack Presentation Oct 07

    24/36

    time to break stuff

    question - ok, so how doesActiveRecord operate underconcurrency?

    answer - creates a connection-per-threadwhen allow_concurrency is true

    exhaust max-connections, anyone?

    lets try!

  • 8/14/2019 Rack Presentation Oct 07

    25/36

    %w(rubygems rack active_record).each { |dep| require dep }AR = ActiveRecord::BaseAR.allow_concurrency = trueAR.establish_connection(:adapter => 'mysql',:username => 'root',

    :database => 'flashden')def user_count AR.connection.select_all('select * from users limit 1000')endapp = lambda { |env| [200, {}, user_count.inspect] }Rack::Handler::Mongrel.run(app, :Port => 3000)

  • 8/14/2019 Rack Presentation Oct 07

    26/36

    ab -c 100 -n 100 http://0.0.0.0:3000/

  • 8/14/2019 Rack Presentation Oct 07

    27/36

    Thu Oct 25 17:01:09 +1000 2007: ERROR: Too many connectionsThu Oct 25 17:01:09 +1000 2007: ERROR: Too many connectionsThu Oct 25 17:01:09 +1000 2007: ERROR: Too many connectionsThu Oct 25 17:01:10 +1000 2007: ERROR: Too many connectionsThu Oct 25 17:01:10 +1000 2007: ERROR: Too many connectionsThu Oct 25 17:01:10 +1000 2007: ERROR: Too many connectionsThu Oct 25 17:01:10 +1000 2007: ERROR: Too many connectionsThu Oct 25 17:01:10 +1000 2007: ERROR: Too many connections

    Thu Oct 25 17:01:10 +1000 2007: ERROR: Too many connectionsThu Oct 25 17:01:10 +1000 2007: ERROR: Too many connectionsThu Oct 25 17:01:10 +1000 2007: ERROR: Too many connectionsThu Oct 25 17:01:10 +1000 2007: ERROR: Too many connectionsThu Oct 25 17:01:10 +1000 2007: ERROR: Too many connectionsThu Oct 25 17:01:11 +1000 2007: ERROR: Too many connectionsThu Oct 25 17:01:11 +1000 2007: ERROR: Too many connectionsThu Oct 25 17:01:11 +1000 2007: ERROR: Too many connections

    Thu Oct 25 17:01:11 +1000 2007: ERROR: Too many connections

  • 8/14/2019 Rack Presentation Oct 07

    28/36

    yep, broke it (thats onmax-connections=100)

  • 8/14/2019 Rack Presentation Oct 07

    29/36

    i dunno how to fix it

  • 8/14/2019 Rack Presentation Oct 07

    30/36

    connection pooling?

  • 8/14/2019 Rack Presentation Oct 07

    31/36

    yeah thanks for yourfeedback!

  • 8/14/2019 Rack Presentation Oct 07

    32/36

    adding-on

    use Rack::Builder to add some moresophisticated behaviour, its a DSL like thing

    to construct rack applications

    free logging, exception handling, urlmapping, http authentication, directory

    serving...

  • 8/14/2019 Rack Presentation Oct 07

    33/36

    app = Rack::Builder.new {use Rack::CommonLoggeruse Rack::ShowExceptionsmap "/" douse Rack::Lint

    run MyCustomAwesomeApp.newend

    }

  • 8/14/2019 Rack Presentation Oct 07

    34/36

    so, these bits and bobs

    can make life easier Rack::Reloader

    Rack::Static Rack::ShowExceptions

    Rack::CommonLogger

    Theres a couple more, see docs!

  • 8/14/2019 Rack Presentation Oct 07

    35/36

    links to stuff and etc

    http://rack.rubyforge.org/ http://rack.rubyforge.org/doc/

    http://www.wsgi.org/

  • 8/14/2019 Rack Presentation Oct 07

    36/36

    end!