Rails threads / contexts / fastcgi - can someone explain?

Hi,

Would someone be able to explain how ruby class/object contexts work
from the point of view of a deployed rails application using FASTCGI and
noting there are multiple Ruby processes running (say on dreamhost for
example). Some questions to help clarify what I’m trying to understand:

a) how do incoming URL requests get spread across the multiple Ruby
processes (let’s say there are 5 processes)?

b) What component organising/manages this? (e.g. plugin in apache?)

c) is there any ‘stickness’ that occurs? i.e. where a request from
person A that goes to ruby process 2 the first time will go to process 2
again for the next person A request (I assume no?)

d) is there any sharing of contexts between the ruby processes? i.e.
Can a ruby class variable be “seen” across processes?

e) is there any equivalent to the java static class variable (which can
be accessed from any user request coming in which is being hosted within
the same web-container on the same JVM)? I understand there isn’t an
equivalent in ruby?

f) does the running ruby process handle multiple simultaneous user
requests at the same time? i.e. is it operating in a multi-threaded
mode?

g) If so (for last question) is there any scope for collisions when
using class variables (@@variable), or is each user request (i.e. each
HTTP request) totally isolated from every other request at the
ruby/rails application level? (of course the database would be shared).
i.e. could both users/requests share the same class variable somehow??

h) what non-database caching raw ruby techniques are there for same
caching a bunch of constants stored in a properties type file - perhaps
put the properties/configuration setting in a ruby file itself as
constants. Is it effectively already “cached” once it is "require"ed
via ruby then holding it in memory? or does ruby re-load that file each
time?

i) what would be simplest / rudimentory way to load/cache a bunch of
properties/configuration parameters for an application? (would it be as
per my suggestion in item h)

Signed
Still a bit confused about ruby/rails contexts :slight_smile:

Thanks in advance

On 9/12/06, Greg H. [email protected] wrote:

Hi,

I’m not a FastCGI expert, but I’ll try to answer your questions as best
I can.

Would someone be able to explain how ruby class/object contexts work
from the point of view of a deployed rails application using FASTCGI and
noting there are multiple Ruby processes running (say on dreamhost for
example). Some questions to help clarify what I’m trying to understand:

a) how do incoming URL requests get spread across the multiple Ruby
processes (let’s say there are 5 processes)?

By whatever’s in front of the processes. If you’re using
lighttpd/fastcgi, for example, lighttpd will do the balancing across
the multiple rails fastcgi listeners.

b) What component organising/manages this? (e.g. plugin in apache?)

c) is there any ‘stickness’ that occurs? i.e. where a request from
person A that goes to ruby process 2 the first time will go to process 2
again for the next person A request (I assume no?)

That’s going to depend on the particular implementation. I haven’t
seen it implemented anywhere, but that doesn’t mean that someone
hasn’t done so.

d) is there any sharing of contexts between the ruby processes? i.e.
Can a ruby class variable be “seen” across processes?

By default, no. You can use an in-memory cache accessible by all
listeners (on the same box).

e) is there any equivalent to the java static class variable (which can
be accessed from any user request coming in which is being hosted within
the same web-container on the same JVM)? I understand there isn’t an
equivalent in ruby?

I’m not sure what you’re asking here. There are class variables in ruby.

f) does the running ruby process handle multiple simultaneous user
requests at the same time? i.e. is it operating in a multi-threaded
mode?

It doesn’t.

g) If so (for last question) is there any scope for collisions when
using class variables (@@variable), or is each user request (i.e. each
HTTP request) totally isolated from every other request at the
ruby/rails application level? (of course the database would be shared).
i.e. could both users/requests share the same class variable somehow??

Again, I’m not sure what you’re asking. Rails runs single-threaded.

h) what non-database caching raw ruby techniques are there for same
caching a bunch of constants stored in a properties type file - perhaps
put the properties/configuration setting in a ruby file itself as
constants. Is it effectively already “cached” once it is "require"ed
via ruby then holding it in memory? or does ruby re-load that file each
time?

Put config stuff in the environment files. In production mode those
don’t get reloaded.

-ryan

On Sep 12, 2006, at 3:30 AM, Greg H. wrote:

a) how do incoming URL requests get spread across the multiple Ruby
processes (let’s say there are 5 processes)?

The front end webserver balances between the fcgi listeners. On
dreamhost this would be apache doing that I believe.

b) What component organising/manages this? (e.g. plugin in apache?)

see above

c) is there any ‘stickness’ that occurs? i.e. where a request from
person A that goes to ruby process 2 the first time will go to
process 2
again for the next person A request (I assume no?)

Not with apache and usually not with fcgi. some front end proxies
allow this like pound or nginx. Its called sticky session adn it
makes sure a clients request always goes to the same backend.

With rails I don’t think this is a good idea. You need to code your
rails apps so that any backend can answer a request.

d) is there any sharing of contexts between the ruby processes? i.e.
Can a ruby class variable be “seen” across processes?

No the ruby processes are totally independent. you can share state
through the database or via a drb server or memcached.

e) is there any equivalent to the java static class variable (which
can
be accessed from any user request coming in which is being hosted
within
the same web-container on the same JVM)? I understand there isn’t an
equivalent in ruby?

I’m not familiar with Java enough to know what this means exactly.
But I don’t think rails has what you want here. Can you explain what
you want to do with this and then I can help?

f) does the running ruby process handle multiple simultaneous user
requests at the same time? i.e. is it operating in a multi-threaded
mode?

No each request to rails gets gaurded with mutex. So each of your
rails processes will only serve one request at a time and new
requests will queue up waiting their turn. So you need to watch out
if your users are dong huge file uploads. If you have three fcgi’s
and people try to upload 5 huge files at the same time, two of them
will queue up and wait until one of the other uploads is done.

g) If so (for last question) is there any scope for collisions when
using class variables (@@variable), or is each user request (i.e. each
HTTP request) totally isolated from every other request at the
ruby/rails application level? (of course the database would be
shared).
i.e. could both users/requests share the same class variable somehow??

On each request, your models and controllers are instantiated and go
from there. @@classvars can get confusing because they are visible
throughout the entire inheritance tree from where they are defined.
So you can use these but think it thru carefully if you do as it can
get confusing and if you don’t do it right it can cause leakages
between sessions.

h) what non-database caching raw ruby techniques are there for same
caching a bunch of constants stored in a properties type file -
perhaps
put the properties/configuration setting in a ruby file itself as
constants. Is it effectively already “cached” once it is "require"ed
via ruby then holding it in memory? or does ruby re-load that file
each
time?

If you put a constant in environment.rb it will only load on bootup
and will stay in memory until the procees is killed.

i) what would be simplest / rudimentory way to load/cache a bunch of
properties/configuration parameters for an application? (would it
be as
per my suggestion in item h)

I would make a yaml config file and then load the contents of that
into a constant in environment.rb. That works great for certain
things. Of course you don’t want to store a huge amount of data thins
way but for config options it works great.

Signed
Still a bit confused about ruby/rails contexts :slight_smile:

No worries, its a bit difficult to figure out on your own. But once
you follow a few guidelines it will become clear.

Thanks in advance

You’re welcome!

Cheers-
-Ezra

Thanks heaps Ezra & Ryan for answering. I’ll respond below:

e) Equivalent to Java Static Class

  • I didn’t explain that well my question, but it was really what does
    the
    language offer itself in terms of shared in-memory data across any/all
    requests.
  • Ryan points out there is really no equivalent
  • RYAN: When you mentioned in-memory cache options I guess you were
    referring to some external operating system support? What did you have
    in
    mind for a unix installation?

f) running ruby process handle multiple simultaneous requests

  • EZRA: Tks. Do you whether a typical apache/fastcgi setup will detect
    the
    “I don’t have enough running ruby processes” and start new ones? In
    particular I’m using dreamhost at the moment for hosting & wondering
    whether
    I need to configure anything here myself, or request it from the hosting
    provider.

g) scope for collisions when using class variables (@@variable)

  • Ezra: I’d love to understand what you meant by “think it thru
    carefully if
    you do as it can get confusing and if you don’t do it right it can cause
    leakages between sessions” (i.e. re use of class variables) - are you
    able
    to expand?

i) way to load/cache a bunch of properties/configuration parameters

  • Tks
  • I was considering usage for simple localisation, and have a couple of
    different files each with say 5 to 10 pages of key,value pairs. How do
    this
    sound re size? The only other way would be to hit the database each
    time in
    fact no? i.e. is there any in-between approach that ruby/rails offers
    (e.g.
    lazy-loading type support that is then cached?)

Thanks again
Greg