普通にRuby on RailsをCGI（dispatch.cgi）で動かすと遅すぎてやってられませんが、gateway.cgiを使うと、そこそこの速度で動くようになります。

最初に仕掛けを紹介してしまうと、1回目のアクセスがあったときに常駐プロセスを起動し、2回目以降のアクセスはその常駐プロセスに処理させるようになっています。CGI自体は常駐プロセスに処理を投げるだけなので軽い、というわけです。ただし、１回目のアクセスは通常通りCGIで動作させたくらいの遅さです。

常駐プロセスは一定時間アクセスがないと自動的に終了するので（次のアクセスがあったときにまた起動する）、いろいろ制限のある環境でも使える、かもしれません。

さて、そのgateway.cgiですが、Railsの標準パッケージの中に含まれています。まだexperimentalらしいですが、多少パッチを当てると動きます。

使い方は↓こんな感じです。

$ gem install rails $ gem install fcgi $ RAILS_DIR = / usr / lib/ruby/gems/ 1.8 /rails- 2.0 . 2 $ rails gateway $ cd gateway $ mkdir log/drb_gateway $ chmod 777 log/drb_gateway $ cp $RAILS_DIR /dispatchers/gateway.cgi public / $ cp $RAILS_DIR /lib/commands/ncgi/listener script/ $ cp $RAILS_DIR /lib/commands/ncgi/tracker script/ $ chmod 755 public /gateway.cgi $ patch -p1 < gateway.patch $ ruby script/generate controller Test index $ ruby gateway-test.rb

gateway.patch：

diff -Nurp gateway.orig/public/gateway.cgi gateway/public/gateway.cgi --- gateway.orig/public/gateway.cgi 2008-02-09 22:04:17.000000000 +0900 +++ gateway/public/gateway.cgi 2008-02-09 22:05:53.000000000 +0900 @@ -1,4 +1,4 @@ -#!/usr/local/bin/ruby +#!/usr/bin/env ruby require 'drb' diff -Nurp gateway.orig/script/listener gateway/script/listener --- gateway.orig/script/listener 2008-02-09 22:04:30.000000000 +0900 +++ gateway/script/listener 2008-02-09 22:02:21.000000000 +0900 @@ -14,6 +14,8 @@ class RemoteCGI < CGI self.env_table = env_table self.stdinput = input || StringIO.new self.stdoutput = output || StringIO.new + $stdin = self.stdinput + $stdout = self.stdoutput super() end

gateway-test.rb：

#!/usr/bin/env ruby require ' webrick ' config = { :DocumentRoot => ' . ' , :BindAddress => ' 127.0.0.1 ' , :Port => 3000 , } server = WEBrick :: HTTPServer .new(config) server.mount( ' / ' , WEBrick :: HTTPServlet :: CGIHandler , "#{ Dir .pwd } /public/gateway.cgi " ) trap ( ' INT ' ) { server.shutdown } trap ( ' TERM ' ) { server.shutdown } server.start

Apacheで動かすときはpublic/.htaccessのdispatch.cgiをgateway.cgiに書き換えておく必要があります。

おもしろいのはその動作方法で、常駐プロセスとCGIの通信にはUNIXドメインソケットとdRubyが使われています。一度アクセスするとlog/drb_gatewayディレクトリにソケットが作られます。

常駐プロセスはFastCGIをエミュレーションしており、Railsから見るとFastCGIで動作しているように見えるようです。

このやり方自体はRails以外にも応用できそうです。CGIしか使えない環境を想定する場合は、この方法を実装してみると劇的に体感速度が上がるかもしれません。