On Sun, 2006-05-28 at 19:38 +0200, François SIMOND wrote:
> Here is a rudimentary patch against mongrel-0.3.12.4, that basically works !
> I could not imagine that it would be so easy  :) 

Here's the things that blow up--even with this setting--unless there's
been some *major* improvements in how Rails' was structured:

* Classes mysteriously "disappear" or aren't loaded.  Ruby's dynamic
class loading and instance_eval is not thread safe, so when multiple
threads load rails actions, models, and helpers the Dispatcher throws
random exceptions.
* Model objects used in one thread show up in another thread.  Last time
this was because there were problems with how shared connections were
being used between the different threads.
* Requests mysteriously pick up other thread's request input or output.
No idea why this was.  It's really really weird.
* High load causes database connections to explode exponentially into
the thousands.  This is caused by use Thread.current[] to store the DB
connection, which causes the rails application to connect one time for
each thread.
* Once connected, the connection doesn't go away, but the thread does.
This means that when each thread is created, connects, and then finishes
it's response, the connection is kept around until the GC kills it.
This causes file descriptor leaks that eventually make the whole Mongrel
server stop functioning because the number of open files is greater than
the 1024 select() limit on most systems.
* Long running Mongrel servers start eating lots of memory or stop
running.  This is mostly caused by the connections per thread model not
being cleaned up, but even when this is cleaned out it's still not good
enough.  Files, other thread, popen calls, fork, and many other
resources or notoriously poorly managed by nearly every Rails
programmer.

I started working on fixing these problems way back in the SCGI days,
but the task was so daunting that I just gave up.  So, yes, your little
patch is very easy.  It probably won't work without a lot of extra
effort.

If you're interested in doing some hack-o-tronic work to make this
function, then you'll have to either rule out the above problems (with
more than one request with a browser) or find a way to implement fixes
outside of rails.  Some possible solutions:

1) Rip out anything left over in a Thread.current[] after the rails
request is done.
2) Find a way to mark what request/response/IO objects are assigned to
each thread, and then blow-up if they change during processing.  This
would most likely be a debugging option for people suspecting crossover.
3) Find a way to keep track of what a rails controller opens, and then
make sure it gets closed completely.  This'll be a real realy pain in
the ass since people love to open crap at random and not clean it up.
4) Do a completely pre-loading when a rails application is started in
production mode so that all classes are properly loaded ahead of time
and you don't have to worry about Ruby's lack of thread safety here.

If you're up to the challenge, then give it a shot.  You'll want to
setup a test harness with your current code that thrashes the living
hell out of a real rails application for a long period of time and then
fix everything that comes up.


-- 
Zed A. Shaw
http://www.zedshaw.com/
http://mongrel.rubyforge.org/


_______________________________________________
Mongrel-users mailing list
Mongrel-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/mongrel-users

Reply via email to