nginx

nginxでCGIを動かす

nginxはサーバ本体でCGIの実行をサポートしていない. ただ本当にCGIが使えないと不便なので,代わりにFastCGIにリクエストを飛ばす形でのサポートがある.

FastCGI

通常,CGIはリクエストされるごとにスクリプトを実行して結果を返すようになっているが, 毎回インタプリタを起動するため大量のリクエストが来ると実行速度が遅くなるという問題がある. 1 FastCGI はCGIプロセスをサービス化しておき,ソケット経由でリクエストを受理して結果を返すようにするシステムである. こうすることでWebサーバは毎回CGIのプロセスを立ちあげなくて済み,スループットが向上する. また,プロセスを分離することでセキュリティの向上,Webサーバのアーキテクチャからの独立などの効果もある.

FastCGIサービスを作るには

などの方法がある. 最初の2つは通常のCGIスクリプトの前段にFastCGIサーバを置くもので,最後のものは最初からスタンドアロンなFastCGIサーバとして動くスクリプトを作るものである. ここでは,fcgiwrapを使う方法について説明する. 2 3

CGIに飛ばす設定

設定は https://wiki.archlinux.org/index.php/Nginx#CGI_implementation の通りに行えばよい. まずfcgiwrapサービスを起動しておく.

# systemctl start fcgiwrap.service

次にnginxで,CGIを動かしたいパスに対してfastcgiへリレーする設定を書く. 以下の設定では,ApacheのUserDirっぽい挙動を再現している(単なる趣味). FastCGIに使えるディレクティブは http://wiki.nginx.org/HttpFastcgiModule にあるが, 基本的には root なり alias で読み込むファイルのパスを得られるようにしてから fastcgi.confinclude すれば良い. root を使った設定なら fastcgi.conf でよしなに処理してくれるが, alias を使うとうまく行かないので SCRIPT_FILENAME を自分で設定してやる必要がある.

location ~ ^/~(.+?)/(.*\.fcgi)$ {
    alias /home/$1/public_html/$2;
    fastcgi_pass unix:/var/run/fcgiwrap.sock;
    fastcgi_param SCRIPT_FILENAME $request_filename;
    include fastcgi.conf;
}

これで自作のCGIスクリプトの拡張子をfcgiにしてアクセスすることで,nginxからCGIを呼び出すことができるようになる.

  1. 別にCGIはスクリプト言語でなくてもいいのだが,なんにせよプロセス生成のコストは毎回かかるので嬉しくない.

  2. 最初はHaskellのバインディングを使っていたのだが,うまく動かなかったので諦めた.

  3. fcgiwrapはリクエストごとにCGIの実行プロセスをforkしているので,速度面での改善はあまり期待できないと思われる.