2010年11月28日星期日

Run sinatra application with Apache httpd server over scgi

It's really painful when the README file told me the code works but actually not. This is what I was fighting for running a rack based application on Apache2 over scgi.

Background: On Friday night, I brought a web scalability problem from office that mainly on ruby because we confirmed Webrick sucks and can't work well in REAL production (aka, concurrent users). On gtalk, Kevin provided a number of solutions on scaling out Rails application like lighttpd+fastcgi and mod_rails. But I'm using sinatra + rack. Finally I approached to scgi which is a stable and high-performance solution.

Here's the steps on centos5.5 (things are getting easier on ubuntu but centos is my production use):
  1. Install apache2:
    #yum install httpd httpd-devel
  2. Install mod_scgi:
    #wget http://python.ca/scgi/releases/scgi-1.14.tar.gz
    #cd scgi-1.14/apache2
    #/sbin/apxs -i -c mod_scgi.c
  3. Install ruby-scgi (assume you've got necessary gems like sinatra and rack):
    #gem install scgi
  4. Compose a simple sinatra app for example:
    # /var/www/sample-app/MyApp.rb
    require 'rubygems'
    require 'sinatra/base'

    class MyApp < Sinatra::Base
    set :sessions, true
    set :foo, 'bar'
    set :server, %w[scgi]

    get '/query/' do
    'How you doin'?'
    end
    end
  5. compose a config.ru for rack:
    require 'rack'
    require 'MyApp'

    MyApp.run! :port => 9090
  6. Note: you must create a 'log'directory before running rackup:
    #mkdir /var/www/sample-app/log
    #rackup config.ru &
  7. Create an conf file for your apache2:

    # /etc/httpd/conf.d/MyApp.conf
    LoadModule scgi_module modules/mod_scgi.so

    # Set up a location to be served by an SCGI server process
    SCGIMount /query/ 127.0.0.1:9090


    <location "/query">
    # Enable SCGI delegation
    SCGIHandler On
    # Delegate requests in the "/query" path to daemon on local server, port 9090
    SCGIServer 127.0.0.1:9090
    </location>
  8. Restart your apache2 then issuing request to http://localhost/query/
Enjoy :)