mod_rails aka mod_rack aka mod_ruby

Grzegorz Nosek grzegorz.nosek at gmail.com
Thu Jun 5 21:01:38 MSD 2008


Hi Mike,

On czw, cze 05, 2008 at 05:39:12 +0200, =?ISO-8859-2?Q?Micha=B3_Jaszczyk_ wrote:
> Hi Grzegorz,
> 
> I'll try to defend the idea :).

Many have tried... ;)

> >
> >> And lower memory/cpu/etc consumption.
> >
> > Disagreed. You'll have to keep a Ruby interpreter in every nginx worker
> > process. Also, a Ruby script may block indefinitely (e.g. waiting for a
> > database or an external resource, or simply sleeping just to piss you
> > off), so you'll either need to run many more workers (negating the
> > benefits of the evented programming model), or intercepting sleeping
> > calls to plug them into the main event loop (might be impossible to do
> > in a general way and anyway is non-trivial).
> >
> 
> That's the problem with mod_wsgi too AFAIK. And what does Nginx do
> when one of upstream backends takes too long to produce answer? It's
> all the same, I think and the solution can be the same.

Well, the problem is that nginx knows it's nginx (obviously), and no
code ever blocks on its own. Whenever a request handler must wait for
something, it gives back control to the main event loop. Now, imagine a
Ruby app trying to receive some data from a socket. It'll simply do a
blocking read() and wait. In the meantime, all the other requests
handled by the current worker are stalled because the event loop is not
processed.

> > Note that you'll also have to keep the interpreter state in sync between
> > workers (shared memory?).
> 
> Disagreed. I assume the following: Temporary workflow data are kept on
> one worker only and if this data has to be kept longer that for one
> HTTP request, you can store them in the DB (not very good solution) or
> in something like memcached (better). But it's more about how to do
> clustering, not about how to run Ruby on Nginx, right?

So you're basically after a php-style execution environment using a DB
or memcached as a session store? I.e. restarting the application after
every request? Remember that e.g. a mongrel lives for a long time (esp.
compared to request processing time) to save on startup costs (e.g.
compiling the whole code over and over again).

For me, the biggest advantage of basically everything over PHP is that
the application (not just the language runtime) may keep its state for a
long time, so it makes sense to e.g. do in-process caching of sessions
or frequently accessed data (say, translations, top 10 articles &
stuff).

For version 1.0 consider simple interpreter (vhost) <-> worker process
affinity, and _keep_the_interpreter_state_ between requests. Otherwise,
you've got all the headaches of *both* PHP and Ruby.

> > Running a single interpreter may certainly be useful for dedicated
> > servers but does not address all the needs of the real world.
> 
> What are those then?

I do not pretend to represent the whole real world, but for me a web
server must be:
 - secure
 - lightweight (Rails is a hog, I don't need another one)
 - flexible (including hackable source, one size never fits all)
 - fast (as a bonus; basically I couldn't care less whether nginx
   reaches 2000 or 3000 req/s, it's fast enough already)

Embedding a full-blown interpreter gives you an extra bit of speed at
the expense of both resource usage *and* security.

A real-life (though simplified) example: an nginx server fronting
~20 distinct small Rails apps, each one using a single mongrel.
Total cost: ~600MB for the mongrels plus a rounding error for nginx.
Total (dynamic content) capacity: 20 concurrent requests (one to each
app).

Using an embedded interpreter, you'd either:

 - use 600MB for nginx *and* handle a single dynamic request
 - use n*600MB and handle n requests concurrently
 - start the application anew after every request (thus using only 30MB
   for the currently processed app) and suffer several-second long
   response times as Rails struggles to boot

You could also bring the whole webserver down by simply executing

a = 'a'
loop { a = a + a } # or whatever in Ruby, I'm a Perl guy

and eating the whole memory.

> I use mod_wsgi in heavy production environment and it works just fine
> :). The Python apps aren't very sophisticated, that's true, but anyway
> :). So I think that if Manlio still wants to improve it, Django would
> also work smoothly :).

mod_wsgi is fine for its purposes but I don't think it's a matter of
'improving' to run Django on it. It would be a matter of redesigning the
whole thing.

> So what do you think about the idea anyway? Are you for or against? :)

As far as I'm concerned? I don't think it'll fly but go ahead and prove
me wrong :)

> Apache is doing mod_php for PHP, mod_python and mod_wsgi for Python.
> mod_rails for RoR has just transformed into mod_passenger for Ruby's
> Rack/Rails AND Python's WSGI. So it seems like people need this kind
> of stuff. So Nginx could also have such module, right? :)

I think people think they want this stuff, because "embedding an
interpreter in a web server is fast" and "nginx is fast", so nginx with
an embedded interpreter must be blazing, right? Ruby *is* slow, get over
it ;)

Best regards,
 Grzegorz Nosek






More information about the nginx mailing list