Mod_ruby: what's persistent and what's shared?

i’m tired of being confused about this and i’m hoping someone can clear this
up for me.

when i make a request to apache on a mod_ruby script, i know that the ruby
interpreter is embedded into apache so that a new instace of ruby does not
have to be started every time. so then global variables and class definitions
including class variables persist between connections. right? so if i’m USER1
and i request a ruby app that creates a global variable or an object instance
with a defined class variable, then when USER2 requests the same app, will
the gloabal variable or class variable be set as it was for USER1?

thanks,

···


tom sawyer, aka transami
transami@transami.net

                               .''.
   .''.      .        *''*    :_\/_:     .
  :_\/_:   _\(/_  .:.*_\/_*   : /\ :  .'.:.'.

.’’.: /\ : ./)\ ‘:’* /\ * : ‘…’. -=:o:=-
:/:’.:::. | ’ ‘’ * ‘.’/.’ (/’.’:’.’
: /\ : ::::: = / -= o =- /)\ ’ *
’…’ ‘:::’ === * /\ * .’/.’. ‘._____
* | : |. |’ .—"|
* | _ .–’| || | _| |
* | .-’| __ | | | || |
.-----. | |’ | || | | | | | || |
__’ ’ /"\ | '-."". ‘-’ ‘-.’ '` |.

They persist between connections to the same process

···

Tom Sawyer (transami@transami.net) wrote:

i’m tired of being confused about this and i’m hoping someone can clear this
up for me.

when i make a request to apache on a mod_ruby script, i know that the ruby
interpreter is embedded into apache so that a new instace of ruby does not
have to be started every time. so then global variables and class definitions
including class variables persist between connections. right? so if i’m USER1
and i request a ruby app that creates a global variable or an object instance
with a defined class variable, then when USER2 requests the same app, will
the gloabal variable or class variable be set as it was for USER1?


Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

i’m tired of being confused about this and i’m hoping someone can clear this
up for me.

when i make a request to apache on a mod_ruby script, i know that the ruby
interpreter is embedded into apache so that a new instace of ruby does not
have to be started every time. so then global variables and class definitions
including class variables persist between connections. right? so if i’m USER1
and i request a ruby app that creates a global variable or an object instance
with a defined class variable, then when USER2 requests the same app, will
the gloabal variable or class variable be set as it was for USER1?

It depends?

The Apache parent process may spawn a number of children. Suppose the
request from USER1 is serviced by child A. If the request from USER2
is also serviced by child A, then it’ll be getting the same mod_ruby.
If it’s serviced by a different child, all bets are off.

Moral: You can’t rely on the behavior that you appear to want to rely on.

···

At 10:19 +0900 1/23/03, Tom Sawyer wrote:

thanks,

tom sawyer, aka transami
transami@transami.net

Hi,

i’m tired of being confused about this and i’m hoping someone can clear this
up for me.

when i make a request to apache on a mod_ruby script, i know that the ruby
interpreter is embedded into apache so that a new instace of ruby does not
have to be started every time. so then global variables and class definitions
including class variables persist between connections. right? so if i’m USER1
and i request a ruby app that creates a global variable or an object instance
with a defined class variable, then when USER2 requests the same app, will
the gloabal variable or class variable be set as it was for USER1?

Sadly, from what I understand so far, it’s the “worst of both
worlds”. ;-D

You have to be aware of persistence because global variables do
persist in the Ruby interpreter running in a given httpd child
process.

But, you can’t depend on persistence, because the multiple (forked)
httpd processes that might service your request are all separate.
[Each has its “own” persistence.]

If you make a test script and keep refreshing the page, you’ll
tend to get the same process handling the request, if the HTTP
connection is in a keep-alive state. So you’ll see apparent
persistence from invocation to invocation.

But once a different process takes over and services the request,
you’ll see a whole “different” persistence associated with that
particular process / Ruby interpreter.

Below is a little test script that prints the process number,
and also the contents of a hash that, if all processes were
able to share the same global interpreter data, would grow to
include keys for each process, the value of which would be an
integer incremented each time a given process invoked the
script. (But of course, what you’ll see is that the separate
processes cannot share the same hash/interpreter data.)

(Also if you have access to http://your-server/server-status
you can see a graph in ASCII of the various httpd processes and
their current states, which is nice for seeing one still in the
keep-alive state…)

Hope this helps,

Bill

···

From: “Tom Sawyer” transami@transami.net


#!/usr/local/bin/ruby -w

require “cgi”

$gh ||= Hash.new(0)
$gh[$$] += 1

cgi = CGI.new(“html3”)
cgi.out {
cgi.html {
cgi.body {
cgi.h1 { “Howdy from #$$: #{ $gh.inspect } …” }
}
}
}

#end-of-file

thanks you very much. i understand now. since i did not know for sure i have
been coding as if this were the case. so all is well.

···

On Wednesday 22 January 2003 06:46 pm, Paul DuBois wrote:

The Apache parent process may spawn a number of children. Suppose the
request from USER1 is serviced by child A. If the request from USER2
is also serviced by child A, then it’ll be getting the same mod_ruby.
If it’s serviced by a different child, all bets are off.

Moral: You can’t rely on the behavior that you appear to want to rely on.

[courtesy cc of this posting sent to cited author via email]

In article 018b01c2c280$4634c0e0$fd01a8c0@musicbox,

···

Bill Kelly billk@cts.com wrote:

You have to be aware of persistence because global variables do
persist in the Ruby interpreter running in a given httpd child
process.

But, you can’t depend on persistence, because the multiple (forked)
httpd processes that might service your request are all separate.
[Each has its “own” persistence.]

Imagine you do something like this in your httpd.conf

-=-=-
RubyRequire common-data
-=-=-

and that in common-data.rb you have this:

-=-=-
require ‘dbi’

$DB = DBI.connect(“dbi:mysql:foodb”, “user”, “password”)
-=-=-

Will all instances of httpd share the same $DB ? Remember that it is not
data created by a script or a .rhtml page, it is data created when you
start the httpd server…

Ollivier ROBERT -=- Eurocontrol EEC/ITM -=- roberto@eurocontrol.fr
Usenet Canal Historique FreeBSD: The Power to Serve!

Tom Sawyer wrote:

The Apache parent process may spawn a number of children. Suppose the
request from USER1 is serviced by child A. If the request from USER2
is also serviced by child A, then it’ll be getting the same mod_ruby.
If it’s serviced by a different child, all bets are off.

Moral: You can’t rely on the behavior that you appear to want to rely on.

thanks you very much. i understand now. since i did not know for sure i have
been coding as if this were the case. so all is well.

If you want to be able to rely on globally set variables to be shared and such, you really want a single Ruby app at the recieving end. That is, you want IOWA.

(Or maybe its just me that wants IOWA very badly after a week of PHP
hacking :-/)

···

On Wednesday 22 January 2003 06:46 pm, Paul DuBois wrote:


([ Kent Dahl ]/)_ ~ [ http://www.stud.ntnu.no/~kentda/ ]/~
))_student
/(( _d L b_/ NTNU - graduate engineering - 5. year )
( __õ|õ// ) )Industrial economics and technological management(
_
/ö____/ (_engineering.discipline=Computer::Technology)

Hi,

Imagine you do something like this in your httpd.conf

-=-=-
RubyRequire common-data
-=-=-

and that in common-data.rb you have this:

-=-=-
require ‘dbi’

$DB = DBI.connect(“dbi:mysql:foodb”, “user”, “password”)
-=-=-

Will all instances of httpd share the same $DB ? Remember that it is not
data created by a script or a .rhtml page, it is data created when you
start the httpd server…

My guess is that this would be problematic. Forked children
do inherit copies of the parent’s file handles (I’m assuming
a DB connection is at its heart a file handle / socket?)

My guess as to what would happen would be that the child http
processes would indeed probably “share the same $DB”, assuming
the http.conf processing happens before the children are forked.

However, I think it would likely be a problem to have the
child processes all chattering simultaneously at the DB over
the same connection. I wouldn’t expect that to work properly.
(But I don’t know how it’s implemented, so I could be wrong.)

Regards,

Bill

···

From: “Ollivier Robert” roberto@REMOVETHIS.eu.org

Kent Dahl wrote:

Tom Sawyer wrote:

The Apache parent process may spawn a number of children. Suppose the
request from USER1 is serviced by child A. If the request from USER2
is also serviced by child A, then it’ll be getting the same mod_ruby.
If it’s serviced by a different child, all bets are off.

Moral: You can’t rely on the behavior that you appear to want to rely on.

thanks you very much. i understand now. since i did not know for sure i have
been coding as if this were the case. so all is well.

If you want to be able to rely on globally set variables to be shared and such, you really want a single Ruby app at the recieving end. That is, you want IOWA.

(Or maybe its just me that wants IOWA very badly after a week of PHP
hacking :-/)

Ugh, try writing IOWA in PHP (with a few Seaside-isms thrown in),
which is partly what I’ve been doing contract work on lately. It’s
actually impressive how well it works considering it’s PHP but it’s
horribly horribly painful all the same. :slight_smile:

Julian

···

On Wednesday 22 January 2003 06:46 pm, Paul DuBois wrote:


julian@beta4.com
Beta4 Productions (http://www.beta4.com)

The other option is to have a simple mod_ruby handler and passing
the request into DRb for central processing.

···

Kent Dahl (kentda@stud.ntnu.no) wrote:

If you want to be able to rely on globally set variables to be shared and such, you really want a single Ruby app at the recieving end. That is, you want IOWA.


Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

that approach also makes me queasy… why not simple make a little drb
conection pool? that’d be pretty trival to implement and neatly solves the
problem externally to the web server and individual cgi scripts?

i’ve actually be working on a CGI::Cache for such purposes… it would be just
like a session but able so contain ‘live’ objects, like database handles.

-a

···

On Fri, 24 Jan 2003, Bill Kelly wrote:

Hi,

From: “Ollivier Robert” roberto@REMOVETHIS.eu.org

Imagine you do something like this in your httpd.conf

-=-=-
RubyRequire common-data
-=-=-

and that in common-data.rb you have this:

-=-=-
require ‘dbi’

$DB = DBI.connect(“dbi:mysql:foodb”, “user”, “password”)
-=-=-

Will all instances of httpd share the same $DB ? Remember that it is not
data created by a script or a .rhtml page, it is data created when you
start the httpd server…

My guess is that this would be problematic. Forked children
do inherit copies of the parent’s file handles (I’m assuming
a DB connection is at its heart a file handle / socket?)

My guess as to what would happen would be that the child http
processes would indeed probably “share the same $DB”, assuming
the http.conf processing happens before the children are forked.

However, I think it would likely be a problem to have the
child processes all chattering simultaneously at the DB over
the same connection. I wouldn’t expect that to work properly.
(But I don’t know how it’s implemented, so I could be wrong.)

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

I (almost) have such a beast, and it would be trivial to extend it to
being able to store session data (in that kind of case, something like
Borges would be better, and I have this).

···

ahoward (ahoward@fsl.noaa.gov) wrote:

that approach also makes me queasy… why not simple make a little drb
conection pool? that’d be pretty trival to implement and neatly solves the
problem externally to the web server and individual cgi scripts?

i’ve actually be working on a CGI::Cache for such purposes… it would be just
like a session but able so contain ‘live’ objects, like database handles.


Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

would one say DRb is production strength? this approach intrigues me as well.

···

On Thursday 23 January 2003 05:05 pm, ahoward wrote:

that approach also makes me queasy… why not simple make a little drb
conection pool? that’d be pretty trival to implement and neatly solves the
problem externally to the web server and individual cgi scripts?

i’ve actually be working on a CGI::Cache for such purposes… it would be
just like a session but able so contain ‘live’ objects, like database
handles.


tom sawyer, aka transami
transami@transami.net

In article Pine.LNX.4.33.0301232350560.19862-100000@eli.fsl.noaa.gov,

that approach also makes me queasy… why not simple make a little drb
conection pool? that’d be pretty trival to implement and neatly solves the

Because my Ruby skills are not up to that level… :slight_smile:

problem externally to the web server and individual cgi scripts?

i’ve actually be working on a CGI::Cache for such purposes… it would be
just like a session but able so contain ‘live’ objects, like database
handles.

That would be nice.

···

ahoward ahoward@fsl.noaa.gov wrote:


Ollivier ROBERT -=- Eurocontrol EEC/ITM -=- roberto@eurocontrol.fr
Usenet Canal Historique FreeBSD: The Power to Serve!

tell me more! i will be needing that capability soon. perhaps i could
contribute?

-a

···

On Fri, 24 Jan 2003, Eric Hodel wrote:

I (almost) have such a beast, and it would be trivial to extend it to
being able to store session data (in that kind of case, something like
Borges would be better, and I have this).

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

i sure hope so, otherwise my ‘production’ is doomed! :wink: seriouly though, i
figure DRb is so small that any problem can be tackled with a post to this
list, now take CORBA…

-a

···

On Fri, 24 Jan 2003, Tom Sawyer wrote:

On Thursday 23 January 2003 05:05 pm, ahoward wrote:

that approach also makes me queasy… why not simple make a little drb
conection pool? that’d be pretty trival to implement and neatly solves the
problem externally to the web server and individual cgi scripts?

i’ve actually be working on a CGI::Cache for such purposes… it would be
just like a session but able so contain ‘live’ objects, like database
handles.

would one say DRb is production strength? this approach intrigues me as well.

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

DRb works rather well in this situation, my P133 is able to field a
small request in about .2 - .3 seconds, depending opon complexity. I’m
sure a database connection would be far quicker.

···

Tom Sawyer (transami@transami.net) wrote:

On Thursday 23 January 2003 05:05 pm, ahoward wrote:

that approach also makes me queasy… why not simple make a little drb
conection pool? that’d be pretty trival to implement and neatly solves the
problem externally to the web server and individual cgi scripts?

i’ve actually be working on a CGI::Cache for such purposes… it would be
just like a session but able so contain ‘live’ objects, like database
handles.

would one say DRb is production strength? this approach intrigues me as well.

Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

that approach also makes me queasy… why not simple make a little drb
conection pool? that’d be pretty trival to implement and neatly solves
the problem externally to the web server and individual cgi scripts?

by the way, this queasy solution works fairly well as long as you have a
backup for when you loose the proccess (for a new one), thus i was able to
persist a database connection and a few other things with difficulty and my
sped up multiple times.

i’ve actually be working on a CGI::Cache for such purposes… it would
be just like a session but able so contain ‘live’ objects, like
database handles.

it runs as a seperate service (using DRb)?

i sure hope so, otherwise my ‘production’ is doomed! :wink: seriouly though,
i figure DRb is so small that any problem can be tackled with a post to
this list, now take CORBA…

true true.

i wonder then. if i use DRb would i then also be able to make my app easily
run on a distributed enviornment? i.e. a cluster?

···

On Thursday 23 January 2003 05:05 pm, ahoward wrote:


tom sawyer, aka transami
transami@transami.net

by the way, this queasy solution works fairly well as long as you have a
backup for when you loose the proccess (for a new one), thus i was able to
persist a database connection and a few other things with difficulty and my
sped up multiple times.

have you had any issues sharing one connection between many processes? i mean
what if :

process a :
$db.exec ‘connect foobar_database’

process b :
$db.exec ‘connect barfoo_database’

  1. process a :
    $db.exec # something which has something to do with foobar_database, but
    # it’s connected to barfoo_database!!

it runs as a seperate service (using DRb)?

yes. it’s a totall hack right now, but the idea is a good one i think.
making it totally generic would be tough, but the general idea would be to
place a naming service in a rinda space or simply a drb object which you could
look up other objects by. the rinda space would allow you to leave object
behind between cgi invocations (with all the problems that entails). what i’m
really looking into now is how to efficiently multiplex and bunch of database
connections, eg how to design a connection pool. anyone out there done this?

i wonder then. if i use DRb would i then also be able to make my app easily
run on a distributed enviornment? i.e. a cluster?

yeah. that’s a definitely possibility and one which i’ve considered.

-a

···

On Sun, 26 Jan 2003, Tom Sawyer wrote:

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

have you had any issues sharing one connection between many processes? i
mean what if :

  1. process a :
    $db.exec ‘connect foobar_database’
  2. process b :
    $db.exec ‘connect barfoo_database’
  3. process a :
    $db.exec # something which has something to do with foobar_database,
    but # it’s connected to barfoo_database!!

i get around this by storing the connections in a hash based on connection
info. so connections to different dbs/users get their own connection in the
pool.

here’s the code:

module DBI

singleton instance

provides simple pooling of database connections

note: the pools are defined by dsn and username;

thus optional parameters are expected to be the same for these

def DBI.instance(dsn, user, pass, *args)
@@dbi = {} unless defined?(@@dbi)
@@dbi[“#{dsn}::#{user}”] ||= DBI.connect(dsn, user, pass, *args)
return @@dbi[“#{dsn}::#{user}”]
end

end

it runs as a seperate service (using DRb)?

yes. it’s a totall hack right now, but the idea is a good one i think.
making it totally generic would be tough, but the general idea would be to
place a naming service in a rinda space or simply a drb object which you
could look up other objects by. the rinda space would allow you to leave
object behind between cgi invocations (with all the problems that entails).
what i’m really looking into now is how to efficiently multiplex and bunch
of database connections, eg how to design a connection pool. anyone out
there done this?

very cool. sorry i don’t really have any expertise in this to help. the above
DBI.instance is my extent. let me know how it goes though.

i wonder then. if i use DRb would i then also be able to make my app
easily run on a distributed enviornment? i.e. a cluster?

yeah. that’s a definitely possibility and one which i’ve considered.

see. now that would be the best reason to use it, i think.

···

On Saturday 25 January 2003 08:12 pm, ahoward wrote:


tom sawyer, aka transami
transami@transami.net