[ANN] acgi-0.0.0

URIS

   http://codeforpeople.com/lib/ruby/acgi/

SYNOPSIS

   as·sid·u·ous (adj.)

     1. constant in application or attention; diligent: an assiduous worker who
     strove for perfection.

     2. unceasing; persistent: assiduous research.

   acgi : assiduous or ara's cgi (emphasis on the 'ass' in assiduous) a drop-in
   replacement for ruby's built-in cgi that provides copious features such as

     - persistence
     - speed
     - simplicity
     - familiarity
     - no apache modules
     - browser neutrality
     - could easily be made platform independent
     - ability to install via ftp
     - no special webserver setup or privledges required
     - session affinity (no process pool) so mem caching is simple
     - 91 lines of ruby code

ARCHITECHTURE

   the design of acgi is similar to that of fastcgi (http://www.fastcgi.com) but
   requires no external modules, configuration of apache, etc.

   a acgi application consists of a cgi server backend which loops, handling all
   incoming requests; the requests are delegated to this backend server via a
   simple, fast to start up, 'index.cgi' program written in c. communication
   between 'index.cgi' and it's backend server is via named pipes (fifos):

···

-------------
                         > index.cgi | <- transient (compiled c code)
                         -------------
                         > > >
                         > fifos for stderr, stdout, stdin, env
                         > > >
                        / | \
                 ------------------------------
                 > >
                 > cgi server | <- persistent (looping ruby code)
                 > >
                 ------------------------------

   note that the architechture is similar in spirit to fastcgi - it provides
   speed by avoiding startup overhead and redundant work like database connection
   setup. in this case, contrasted with fastcgi, the whole thing takes place
   outside of the webserver in the application domain.

REQUEST CYCLE

   - request comes in to web server

   - request is passed to index.cgi, a very simple compiled c program which in
     turn does the following

       - make sure the ruby server is running, spawn it in the background iff
         required. this is a non-blocking operation that functions as a simple
         process manager to ensure a server is running at all times.

       - aqurire a lock to prevent other invocations of index.cgi from
         overlapping - all invocations procede one at a time in the order of
         receipt. there are never concurrent requests to the server.

       - serialize the environment and send it down a fifo

       - read any stderr/stdout from the ruby server via fifos and write them to
         stderr/stdout respectively

       - release lock

   - the ruby server, for it's part, does the following

     - aquire a lock which prevent multiple copies from running simoultaneously.
       this is the same lock the c program checks.

     - loops

       - loading the environment

       - handling request with stderr/stdout/stdin redirected

   the cycle is mostly transparent to the cgi progam. to convert an existing cgi
   program to an acgi program one would simply change

     require 'cgi

     cgi = CGI::new
     establish_database_connection
     generate_content

   to

     require 'acgi

     establish_database_connection

     ACGI::each_cgi do |cgi|
       generate_content
     end

IMPLEMENTATION

   shoddy.

   this version is proof of concept only!!! it's likely to run only on linux,
   though it may run on many *nix platforms. or maybe not. there is little to
   no error checking, the sun could explode if you run the example program.
   security is not considered.

RUNNING THE EXAMPLE

     - unpack tarball in webroot
     - make
     - point browser at http:://your.host.com/path/where/you/unpacked/index.cgi

   obviously you'll need cgi setup for you web server, ruby installed, etc.

     - try changing server.rb and running 'make restart'

BUGS

   > 42

WHY?

   i think the idea is neat enough to pursue. i'd like to get a minimal package
   going that supported windows and *nix. if you are interested in participating
   please contact me. mostly i'm in need of windows c/ipc knowledge.

EMAIL

   ara [dot] t [dot] howard [at] noaa [dot] gov

-a
--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna

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

oops - forgot to mention this depends on having posixlock installed - the
README is updated and the dist now included posixlock in the tar.gz.

cheers.

-a

···

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna

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

Thank you for this Ara,

···

On 7 Sep 2005, at 21:25, Ara.T.Howard wrote:

  this version is proof of concept only!!! it's likely to run only on linux,
  though it may run on many *nix platforms. or maybe not. there is little to
  no error checking, the sun could explode if you run the example program.
  security is not considered.

1. I can confirm that your example script works on Mac OS X Tiger 10.4.2 once the posixlock extension is installed.
2. Do error messages caused by me miss-coding my cgi scripts go anywhere accessible when using acgi?

Tom

--
http://tom.counsell.org

Hi,

Being in the process of evaluating alternatives and possible replacements for our FastCGI tier, I must say that this was the most interesting week for a long time in this matter. We currently experience the seemingly (too) common weirdnesses of Apache2+mod_fastcgi+fcgi setups (i.e. mem leaks, eratic 500 errors (unable to contact fcgi backend).

Last night I did a flawless integration of Zed Shaw's Ruby/Event+Myriad SCGI into our current (No rails) Apache2 setup. Although not fully plugged in the rest of our framework, the results are already quite promising.

I will then carefully look into your initiative and see how it competes/complements Zed's approach. Unfortunately I have no need of Windows support at the moment but it is definitely a big plus for acgi.

Thanks for a great annoucement, I'm sure it deserve a less humble 0.0.0 version number :smiley: !

Best regards,

···

--
Katarina

P.S.

In case anyone missed it, Zed's annoucement was here:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/155427

Thank you for this Ara,

  this version is proof of concept only!!! it's likely to run only on linux,
  though it may run on many *nix platforms. or maybe not. there is little to
  no error checking, the sun could explode if you run the example program.
  security is not considered.

1. I can confirm that your example script works on Mac OS X Tiger 10.4.2
once the posixlock extension is installed.

great!

2. Do error messages caused by me miss-coding my cgi scripts go anywhere
accessible when using acgi?

not yet. if you look at index.c or alib.rb you'll see that only stdout is
currently processed. stdin and stderr are essentially ignored. this is
because i need to write someting portable that does the following in index.c:

   if stdin has data
     send it down the pipe
   end

   while data from stdout or stderr pipes
     relay stdout from pipe to stdout
     relay stderr from pipe to stderr
   end

and - in the ruby code - i need to add the following logic

   if stdin_pipe.has_data?
     redirect STDIN => stdin_pipe
   end

so http posts would work (which come in on stdin). the ruby code is already
setup to deal with stderr (but c program is not). basically i didn't want to
spend the time to do this portably if there wasn't any interest.

however - you don't have to fumble in the dark guessing if you're program
runs. the way acgi.rb is setup only on instance of a servlet can run at once
and the c program will not attempt to spawn another if it finds one running.
therefore there is no harm in starting you cgi servelet from a terminal where
you can see all the stderr for yourself. so could do something like the
following in a terminal.

   - just run at the terminal. here stderr will appear on the console. or, if
     your script has a syntax error - it won't even start:

     ~ > ruby ./server.rb </dev/null

   - run using a file full of key=value pairs for testing, letting stderr go to
     console.

     ~ > ruby ./server.rb <key_val.txt

   - just run at the terminal. send stderr to a log. view the log using tail:

     ~ > nohup ruby ./server.rb </dev/null 2>./server.log &

     ~ > tail -F ./server.log

obviously you need to kill any running instance of your servlet before doing
this or a new instance will refuse to start - so someting like

   ~ > ps -elf | grep server.rb

   ~ > kill -9 $pid

of course, for syntax errors, there is always 'ruby -c' too.

btw. i forgot to add the benchmarks to the README, but on my box a cgi
running under acgi.rb is about 4/5 times faster (approx. 100 requests per
second) as compared to the same code written using plain ruby cgi (approx. 20
requests per second). the server.cgi program included in the dist is the same
code as server.rb (the servlet) but meant to run as a cgi. any chance you
could benchmark both using

   # profile acgi

     ~ > ab -n100 http://yourhost/path/index.cgi

   # profile normal cgi

     ~ > ab -n100 http://yourhost/path/server.cgi

and let me know the results?

kind regards.

-a

···

On Fri, 9 Sep 2005, Tom Counsell wrote:

On 7 Sep 2005, at 21:25, Ara.T.Howard wrote:

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna

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