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





This *rules*. Thanks!
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?
Very cool. Thanks, Ezra, and thanks to the Ebb and Thin developers.
Awesome! New gem version of Thin including this change should be out this weekend.
Nice. This is great news. The Rails deployment space is getting very interesting lately.
Scratch that. the *RUBY* web app deployment space, that is.
I saw the commit on github a couple days ago. Cool stuff Ezra.
Woops. Now that I look again it was yesterday. http://github.com/wycats/merb-core/commit/289e65e5d35814f7bfc2ca91d01782b2e66eb5fa
Very cool that they, and you added support for this. Rock on.
sweet. ebb 0.2 with support for this be coming this weekend too
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?
Sounds very cool. Look forward to actually trying it out.
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...
@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.
Noice.
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?
@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?
@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..