Mod_rails aka mod_rack aka mod_ruby

Hi guys,

I did a little research on how Nginx supports Ruby/Rails and if I’m
right, you can only do proxy or FastCGI to make it working. So I
thought… There’s this mod_wsgi module for Python apps which I have
recently used and I find it really great. Why not do the same for
Ruby/Rails? I’m a CS student, I’m looking for a subject for my masters
thesis and I thought that maybe I could create such module. I have
some questions:

  1. Do you think that making mod_ruby/mod_rack/mod_rails is a good idea?
  2. Do you know if someone is already working on something like that?
  3. Do you think it would be useful?
  4. Would you/your friends/collegues be happy if you had such a module
    for Nginx? :slight_smile:

Regards,

Mike

I personally think a mod_rack would be a great idea of nginx. wsgi was a
great thing for unifying python apps, and since ruby is very close but
in its infancy a mod_rack tie with nginx might allow the community to
shift focus on integration to other things.

Michał Jaszczyk wrote:

  1. Do you think that making mod_ruby/mod_rack/mod_rails is a good idea?

Phillip B Oldham
The Activity People
[email protected] mailto:[email protected]


Policies

This e-mail and its attachments are intended for the above named
recipient(s) only and may be confidential. If they have come to you in
error, please reply to this e-mail and highlight the error. No action
should be taken regarding content, nor must you copy or show them to
anyone.

This e-mail has been created in the knowledge that Internet e-mail is
not a 100% secure communications medium, and we have taken steps to
ensure that this e-mail and attachments are free from any virus. We must
advise that in keeping with good computing practice the recipient should
ensure they are completely virus free, and that you understand and
observe the lack of security when e-mailing us.

I think my previous post didn’t reach the list. Sorry if you get a
duplicate, it’s my first post :).

Mike

---------- Forwarded message ----------
From: MichaÅ‚ Jaszczyk [email protected]
Date: 2008/6/5
Subject: mod_rails aka mod_rack aka mod_ruby
To: [email protected]

Hi guys,

I did a little research on how Nginx supports Ruby/Rails and if I’m
right, you can only do proxy or FastCGI to make it working. So I
thought… There’s this mod_wsgi module for Python apps which I have
recently used and I find it really great. Why not do the same for
Ruby/Rails? I’m a CS student, I’m looking for a subject for my masters
thesis and I thought that maybe I could create such module. I have
some questions:

  1. Do you think that making mod_ruby/mod_rack/mod_rails is a good idea?
  2. Do you know if someone is already working on something like that?
  3. Do you think it would be useful?
  4. Would you/your friends/collegues be happy if you had such a module
    for Nginx? :slight_smile:

Regards,

Mike

What advantage would mod_ruby have over simply proxying requests to
Mongrel?

Sergej

Well, speed, hopefully. And lower memory/cpu/etc consumption. And it
may be easier to create an app an run it under Nginx instead of
configuring Mongrel, proxying etc. Also a bit less things to take care
of. Basically, reasons for mod_ruby are the same as for mod_wsgi.

Thanks,

Mike

W dniu 5 czerwca 2008 16:03 użytkownik Rapsey [email protected]
napisał:

less moving parts? easier deployment? fewer points of failure?

Hi Mike,

(sorry for raining on your parade ;))

On Thu, Jun 05, 2008 at 04:22:44PM +0200,
=?ISO-8859-2?Q?Micha=B3_Jaszczyk_ wrote:

Well, speed, hopefully.

Agreed.

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

Note that you’ll also have to keep the interpreter state in sync between
workers (shared memory?).

Another approach would be to spawn a pool of interpreters communicating
with nginx via some pipes but now you’ve got a sort of in-process proxy.

And it
may be easier to create an app an run it under Nginx instead of
configuring Mongrel, proxying etc. Also a bit less things to take care

Do you envision the possibility of running several independent
applications (keeping state between requests but not mixing e.g. two
vhosts), each under a different UID and with specific rlimits and stuff?

Running a single interpreter may certainly be useful for dedicated
servers but does not address all the needs of the real world.

Also, how would you like to handle detecting code changes and reloading
the application?

of. Basically, reasons for mod_ruby are the same as for mod_wsgi.

AIUI, mod_wsgi isn’t a universal module but is mostly useful for
embedding rather simple Python code into nginx.

I remember asking Manlio some time ago about it and he said (more or
less) that embedding e.g. Django via mod_wsgi would be pretty insane,
so I think it would hold twice as true for e.g. Rails.

Of course, I’d like to be proven wrong and hopefully Manlio will step in
to correct me. :slight_smile:

Best regards,
Grzegorz N.

Hi Grzegorz,

I’ll try to defend the idea :).

2008/6/5 Grzegorz N. [email protected]:

Hi Mike,

(sorry for raining on your parade ;))

On Thu, Jun 05, 2008 at 04:22:44PM +0200, =?ISO-8859-2?Q?Micha=B3_Jaszczyk_ wrote:

Well, speed, hopefully.

Agreed.

Cool :).

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.

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?

Another approach would be to spawn a pool of interpreters communicating
with nginx via some pipes but now you’ve got a sort of in-process proxy.

And it
may be easier to create an app an run it under Nginx instead of
configuring Mongrel, proxying etc. Also a bit less things to take care

Do you envision the possibility of running several independent
applications (keeping state between requests but not mixing e.g. two
vhosts), each under a different UID and with specific rlimits and stuff?

I kind of do, I’m doing that kind of stuff using mod_wsgi right now.
Anyway, I’m open to all feature requests :).

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?

so I think it would hold twice as true for e.g. Rails.

Of course, I’d like to be proven wrong and hopefully Manlio will step in
to correct me. :slight_smile:

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 :).

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

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? :slight_smile:

Regards,

Mike

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… :wink:

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? :slight_smile:

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

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? :slight_smile:

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

Best regards,
Grzegorz N.

Grzegorz N. ha scritto:

[…]

AIUI, mod_wsgi isn’t a universal module but is mostly useful for
embedding rather simple Python code into nginx.

Right, but of course we must agree on what “simple” means.

I remember asking Manlio some time ago about it and he said (more or
less) that embedding e.g. Django via mod_wsgi would be pretty insane,
so I think it would hold twice as true for e.g. Rails.

Yes, usually it is insane, for several reasons.
Django (like Ruby on Rails, and other very high level framework) have
the “problem” on hide low level details.

This is fine, but this also means that you can write code that it is
easy to write but completely inefficient.

Of course, I’d like to be proven wrong and hopefully Manlio will step in
to correct me. :slight_smile:

Unfortunately this question does not have an easy answer.
You should really make good tests.

Fortunately know we have many good implementations of WSGI so that we
can test an application in several environments:
Apache mod_wsgi, Nginx mod_wsgi, and so.

Best regards,
Grzegorz N.

Manlio

On czw, cze 05, 2008 at 10:34:01 +0200, Manlio P. wrote:

AIUI, mod_wsgi isn’t a universal module but is mostly useful for
embedding rather simple Python code into nginx.

Right, but of course we must agree on what “simple” means.

Yeah, maybe ‘simple’ was the wrong word, it probably should be
‘low-level’ or ‘specialised’.

I remember asking Manlio some time ago about it and he said (more or
less) that embedding e.g. Django via mod_wsgi would be pretty insane,
so I think it would hold twice as true for e.g. Rails.

Yes, usually it is insane, for several reasons.
Django (like Ruby on Rails, and other very high level framework) have
the “problem” on hide low level details.

This is fine, but this also means that you can write code that it is
easy to write but completely inefficient.

True, and while it’s a moderate problem when the app server is
standalone, it can become a major bottleneck when embedded into the web
server.

Of course, I’d like to be proven wrong and hopefully Manlio will step in
to correct me. :slight_smile:

Unfortunately this question does not have an easy answer.
You should really make good tests.

Fortunately know we have many good implementations of WSGI so that we
can test an application in several environments:
Apache mod_wsgi, Nginx mod_wsgi, and so.

Yes, but this means that you cannot drop any random application into
nginx. And safely running web apps over which I have little control is
essential for me.

Basically, it’s the whole point of my argument against mod_ruby for
nginx – it’ll never be as flexible as a standalone server.

OTOH, one thing I’d love to see would be something like a full-blown Lua
interpreter as a configuration parser.

Best regards,
Grzegorz N.

Grzegorz N. ha scritto:

On czw, cze 05, 2008 at 10:34:01 +0200, Manlio P. wrote:

AIUI, mod_wsgi isn’t a universal module but is mostly useful for
embedding rather simple Python code into nginx.
Right, but of course we must agree on what “simple” means.

Yeah, maybe ‘simple’ was the wrong word, it probably should be
‘low-level’ or ‘specialised’.

Right.
In fact I’m writing a WSGI framework aimed at be “low-level”:
http://hg.mperillo.ath.cx/wsgix/

True, and while it’s a moderate problem when the app server is
standalone, it can become a major bottleneck when embedded into the web
server.

Right.
Note, however, that if an application is slow on I/O (as an example an
HTTP request), then this can be “optimized” using coroutines
(greenlets).

nginx. And safely running web apps over which I have little control is
essential for me.

Basically, it’s the whole point of my argument against mod_ruby for
nginx – it’ll never be as flexible as a standalone server.

I agree.
However I think that it can be an interesting experiment.
Moreover rack is very simple to implement, more simple than WSGI.

As far as I know, there is also a ruby module for Apache, this may be
the best solution.

Another solution is to use a child process for each request.
Something like CGI, but without having to exec: you can just execute
the Python/Ruby script using the embedded interpreter.

I’m writing a CGI module for Nginx with such feature enabled for Python.

OTOH, one thing I’d love to see would be something like a full-blown Lua
interpreter as a configuration parser.

Me, too.
I don’t know if Igor is still interested.
Unfortunately I don’t have the time.

Best regards,
Grzegorz N.

Regards Manlio

MichaÅ‚ Jaszczyk <jasiu85@…> writes:

Such a module would be useful as a Mongrel replacement. At one point Zed
Shaw
(author of Mongrel) was considering rewriting Mongrel as an Nginx
module. So
it’s not an inherently bad idea.

Performance-conscious setups would use a front-end Nginx process that
proxied
to multiple Nginx/mod_ruby processes.

The question I would ask is: Why is Mongrel insufficient?

If you’re looking for an big Nginx-related project, here are a couple
other
ideas:

  1. Embed a scripting language for configuration, and make it use
    non-blocking
    IO (e.g. for LDAP authentication). This has been batted about in various
    forms
    for some time.

  2. Make Nginx work as an HTTP proxy server (not just a reverse proxy).
    Bonus
    points for caching. HTTP was designed with caching proxies in mind, but
    very
    few have been written. There’s Squid, but I bet Nginx could beat its
    pants off
    in terms of performance. This project would entail a number of useful
    sub-
    projects, e.g. async DNS and HTTP/1.1 upstreams, that will benefit many
    Nginx
    users.

Evan

On Thu, Jun 5, 2008 at 6:42 AM, Micha³ Jaszczyk [email protected]
wrote:

  1. Do you think that making mod_ruby/mod_rack/mod_rails is a good idea?

My answer to this is: no, because a whole Ruby VM and application
stack are too much to mix together with the front-end webserver. It’s
the opposite of separation of concerns. Nginx is lean, mean, and
awesome precisely because it doesn’t try to do this sort of thing.

It just so happens that this is the argument I made in my Railsconf
talk about Nginx:

Adam

The argument about separation of concerns finally makes me agree that
that kind of module may not be the best idea. However some other ideas
emerged, so thanks very much for all the input :). More ideas are
still welcome :).

Cheers,

Mike

W dniu 7 czerwca 2008 04:29 użytkownik Adam W. [email protected]
napisał:

I would love something like #2 (below).
What about an ESI nginx module?
http://www.akamai.com/html/support/esi.html

I just learned about ESI at RailsConf and it sounds and looks amazing.
Everything I read about it makes me say “YES!”.
I would think nginx would be a great platform to build ESI caching on
top of, but I’d could also be totally wrong.

BJ Clark
Inigral
inigral.com

On Wed, Jun 11, 2008 at 9:30 AM, Ed W [email protected] wrote:

Have a look at “Passenger” for apache - this kind of came at the problem
from a different direction, but they seem to be building a mod_rack module
in a roundabout kind of way. Performance appears to be higher than mongrel
with the added benefit that the host webserver is completely aware of
queuing and can do much better load balancing and scaling up/down of cgi
instances.
All those other features are the main reasons for putting CGI straight into
the webserver - anyone can simply proxy to a mongrel cluster…

Phusion Passender, aka mod_rails (http://www.modrails.com) is based on
the same principle as Lighttpd and mod_fcgi, where the web server
spawns Rails in multiple worker processes that are child processes of
the web server. The web server itself manages the lifetime of these
workers.

Unlike Lighttpd and mod_fcgi, however, Passenger optimizes memory
usage by forking every worker off a “spawn server” that preloads Ruby
and Rails, meaning that thanks to kernel copy-on-write, the worker
processes will share much of the code and data with the parent
process.

Since Ruby’s garbage collector is not copy-on-write-friendly, these
guys maintain a fork of Ruby that’s patched with a bunch of
copy-on-write optimizations.

http://www.modrails.com/documentation/Architectural%20overview.html

I think the idea of running an interpreter inside Nginx is ridiculous,
but having the web server spawn child processes is a good idea – as
long as it’s stable. My experience with using Lighttpd + FastCGI +
Rails for a year or so was pretty grim, but I’m sure it’s technically
doable.

Alexander.

On Wed, Jun 11, 2008 at 7:17 AM, Alexander S. [email protected]
wrote:

I think the idea of running an interpreter inside Nginx is ridiculous,

Yes. Not only ridiculous inside of Nginx, but inside of any server.
It’s just bad design. And yes far too many web servers out there use
bad design - Apache, etc.

but having the web server spawn child processes is a good idea – as
long as it’s stable. My experience with using Lighttpd + FastCGI +

Who can guarantee the stability?

Phillip B Oldham wrote:

I personally think a mod_rack would be a great idea of nginx. wsgi was
a great thing for unifying python apps, and since ruby is very close
but in its infancy a mod_rack tie with nginx might allow the community
to shift focus on integration to other things.

Rack seems to be where much of the market is heading at the moment, led
at least by the ruby community - seems to be suitable for just about any
web language to interface to

Have a look at “Passenger” for apache - this kind of came at the problem
from a different direction, but they seem to be building a mod_rack
module in a roundabout kind of way. Performance appears to be higher
than mongrel with the added benefit that the host webserver is
completely aware of queuing and can do much better load balancing and
scaling up/down of cgi instances.

All those other features are the main reasons for putting CGI straight
into the webserver - anyone can simply proxy to a mongrel cluster…

Ed W

If you want a web server that can handle rails, use
apache+mod_passenger. If you want php, then use apache+mod_php.

There are so many advantages of separating mongrel from nginx (for
instance), so for once and for all leave Nginx as lean and efficient
as possible, that’s the way I love it.