Deferred requests with merb, ebb and thin

Posted by ezmobius Fri, 18 Apr 2008 06:20:00 GMT

There is a classic tradeoff between threaded servers and event driven servers. Event driven servers tend to be much faster than threaded servers when all the requests are fairly fast. But the event model falls down if you have long requests like file uploads or reporting actions. This is because the long action blocks the event loop, effectively keeping other requests from running.

There are two new event driven ruby webservers at your disposal these days, Thin and Ebb. Both of these servers support the Rack web server interface that merb uses. Until now both of these servers were not the best choice for file uploads or long blocking actions but that’s all changing.

Both ebb and thin have added a deferred?(env) method to their rack adapter interface. Both webservers will call this method on your Rack @app object before they call your call(env) method. This allows your rack adapter to determine if the request should be run in its own thread if it’s slow.

I’ve just committed support for this deferred_actions construct in merb-core. If you want to run on thin or ebb but you have say a file upload action and some slow reporting actions you could add this to your init.rb in your app:

Merb::Config[:deferred_actions] = ["/uploads/create", "/reports/longaction"]

What this means is that all of your actions will run in fast event driven mode except for requests to /uploads/create and /reports/longaction. Any request for either of these urls will be served from a newly spawned thread, all other requests will be served by the main event loop.

This allows us to have the best of both world. Combining threaded and event driven styles to use the strengths of both makes a lot of sense here.

Cheers to the authors of ebb and thin for making the same interface. All of this requires the HEAD versions of ebb or thin so if you want to play along at home you will need to build thin or ebb from source on github: ebb and thin

Tags , ,  | 18 comments


  1. Yaroslav said about 2 hours later:
    This *rules*. Thanks!
  2. Ed Spencer said about 4 hours later:
    Awesome stuff, we've got an app with some long reports which could take advantage of that - not using Merb though sadly... any idea if this is/will be possible with Rails?
  3. Doug said about 6 hours later:
    Very cool. Thanks, Ezra, and thanks to the Ebb and Thin developers.
  4. macournoyer said about 8 hours later:
    Awesome! New gem version of Thin including this change should be out this weekend.
  5. nap said about 9 hours later:
    Nice. This is great news. The Rails deployment space is getting very interesting lately.
  6. nap said about 9 hours later:
    Scratch that. the *RUBY* web app deployment space, that is.
  7. Tim Dysinger said about 12 hours later:
    I saw the commit on github a couple days ago. Cool stuff Ezra.
  8. Tim Dysinger said about 12 hours later:
    Woops. Now that I look again it was yesterday.
  9. Daniel Fischer said about 13 hours later:
    Very cool that they, and you added support for this. Rock on.
  10. ry said about 14 hours later:
    sweet. ebb 0.2 with support for this be coming this weekend too
  11. AnĂ­bal Rojas said 1 day later:
    I like pretty much the idea, the problem with this approach is too many "slow" request being serviced, generating too many threads for the system resources to handle, memory, cpu. Or am I missing something in the picture?
  12. Justin Pease said 1 day later:
    Sounds very cool. Look forward to actually trying it out.
  13. Todd said 5 days later:
    Seems like something is wrong here... event loop should be faster... event handlers for file upload are all writes and reads right? Unless something else is going on during the file upload, it should be able to stay mostly in kernel space during the upload - freeing the event loop to accept more incoming requests... At any rate this seems really good for long requests that are doing a lot of user space processing...
  14. Ezra said 5 days later:
    @Todd - you are correct in that during the transfer of data from the client to the server it does not block the event loop. But when your app needs to parse the multi part request body and then do whatever other file processing your action does that will definitely block the event loop if you don't spin off your own thread.
  15. R. Elliott Mason said 6 days later:
  16. Bob Aman said 10 days later:
    Ok, so what about Rack middleware? If you wrap your app in any of the Rack middleware classes, thin/ebb interface with the middleware rather than the app itself. Because the deferred? method isn't part of the official Rack API, thin/ebb don't relay the deferred? method (they don't define a deferred? method at all) and the method on your app never gets called. Aside from monkey-patching and avoiding Rack middleware entirely, what options are there?
  17. Ezra said 11 days later:
    @Bob- good point, if you wrap your app in any middleware you are on your own with this one. But perhaps we could add a deferred? method to the middleware that recursively checks defined? on any middleware wrapped apps and returns if any of them say yes?
  18. Ben Schwarz said 25 days later:
    @Ezra What if I have dynamic urls or permalinks? Perhaps the deferred action setting could be implemented much like the cache_actions method for a controller. That way the the deferred call would be pretty transparent..

(leave url/email »)

   Preview comment