http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html
- 日本語訳が某所にあったのをgoogle経由で見つけたのですが、どうも、非公開っぽいものだったらしく、現在は403になってしまったので、その元となった英語マニュアルにリンクし直しました。
- fastcgi.comのものには、suexec関連の記述が抜けているので、こっちの方が良いかもしれません。
- 「9acdfcgi」で検索すると、日本語訳も、アチコチで発見できる様子……。合法かどうかは知らないが。
折角なので、今まで自分がmod_fastcgiを使ってきたノウハウ(という程のモノでもないが)を書いてみる。
(先に断っておきますが、Apache?の1系の話です。2系についても当てはまるとは思いますが。ちなみに、一番上のibmの方のマニュアルは、2系ベースのようです)
基礎
- mod_fastcgiを使ったfastcgi動作には、動的(dynamic)、静的(static)、外部(external)の三種類がある。
- dynamicは、始めてアクセスがあった段階でプロセスを起動し、以後は常駐する。
- 主に、.htaccessを使って、以下のどっちかを使って行われる事が多い
- SetHandler fastcgi-script
- AddHandler fastcgi-script .fcgi
- 詳細は、下記のhttpd.confの例を見てください
- staticは、httpdが起動した段階でプロセスを起動し、そのまま常駐。
- externalは、httpd側はプロセス起動を行わなずに、既に起動されているfastcgiプロセスと通信を行って、レスポンスを得る(多分)
- fastcgiプロセスは別サーバにあっても良い(tcpで通信する)
- 自分は使った事が無いのでよく知らない…‥。
httpd.confの設定及び挙動について
- 基本的には、
- AddHandler fastcgi-script .fcgi
- AddType application/x-httpd-fcgi .fcgi
- みたいにしてfcgi用拡張子を追加するか、.htaccessに
- <Files "pw-fcgi.cgi">SetHandler fastcgi-script</Files>
- のように直接特定ファイルを指定してfcgi化するか、で使う。
- どちらの場合も動的(dynamic)起動になるので、初めてアクセスがあった段階で、fcgiプロセスが起動する。
- 動的起動の場合、FastCgiConfigディレクティブで、細かなパラメータ設定を行う。
- 尚、FastCgiConfigディレクティブは、サーバ全体で一つの設定を持つようで、Apache?で普通に行われる「ココのヴァーチャルホスト内でだけココのパラメータはここの数」みたいな設定はどうも、出来ないっぽい。
- 普通、fastcgiを使う場合は、動的起動な事が殆どだと思う。
FastCgiConfigディレクティブで行える設定などの一部を紹介
- FastCgiConfig -maxClassProcesses n
- 一つのfcgi動作させたいスクリプトのファイルに対して、最大何プロセスまでの起動を許すか(多分)。あんまり大きくしても意味がない気がします(自分は2にしています(が、ソレがベターな値かどうかは不明))。
- FastCgiConfig -maxProcesses n
- サーバ全体の、fcgiプロセスの最大数(多分)。アクセスであふれかえったりしてもサーバマシン全体が死なないように、それなりの値をセットしましょう。
- FastCgiConfig -autoUpdate
- コレを行っておくと、fcgi動作させているスクリプトファイルのタイムスタンプか何かを見て、スクリプトファイルが更新されているようなら、fcgiプロセスを再起動するようになる…‥気がする。
- FastCgiConfig -restart
- よく分からないのですが、「上の-autoUpdateの挙動が怪しい時には、コレも指定すると良い」と、マニュアルに書いてあったような気がします。詳細不明。
- ‥…と思っていたのですが、-autoUpdateの日本語訳を読んだところ、「このオプションが -restart で使用されると、未解決の問題(バグ)が存在する場合があります」と、正反対の意味だった‥…。
- という訳で、-autoUpdateと-restartは同時に使わない方がよさそうです。
- 尚、コレは、「fcgiプロセスの障害時(異常終了したりとか)の時に、自動的に再起動する」というオプションのようです(つまり、異常終了後にまた勝手に起動される)。なので、オフにしておいた方が無難だと思います。
- FastCgiConfig -startDelay n
- http://lists.sourceforge.jp/mailman/archives/gauche-devel-jp/2004-February/000583.html
- コレは知らなかった…‥。こんな設定だったのですか…‥(だから、長い間アクセスが無くてスワップアウトしてる状態のfcgiプロセスにアクセスしたら、プロセスが二個に増えてたのか…‥)(尚、自分の経験からすると、こんな感じで増えたプロセスは、五分間ぐらいアクセスが無いと、最低一個を残して、自動的に終了させられるようです)。
- コレは多分、ちゃんとしたマルチプレクシング無しに、平行にアクセスを捌けるようにする為の、苦肉の策のような気がする。或いは、fcgiプロセス内で無限ループした時等にも他のクライアントはアクセス可能なようにする為なのか?
- そうですね、多重化なしだとあっさりブロックしてしまうので、複数起動するしかないでしょう(でないとCGIにも劣る)。
FastCGIの本道ではないと思いますが。--fuyuki
- FastCgiConfig -killInterval n
- 多分、上の「五分間ぐらい」を指定する為のパラメータだと思うのですが、未確認。
※正しい内容は、一番上のリンクから辿れるページから確認しましょう。
インストール時
- mod_soを使って、apxsでインストールする場合はすんなり行くが、mod_soを使わずに直接取り込む場合に、Makefileの書き換えが必要な気がする(そのままだと、so要らないのにso作ってa作ってくれないのでエラーが出た記憶がある)(「all: lib」を「all: libfastcgi.a」にでも書き換えた筈)。
faqもどき
- FastCGIでsuexec?使えますか?
- 使えません‥…と自分は思っていたものの、実は使えるようです。
- ibmの英語マニュアルのsuexecのところ
- 尚、fastcgi.comのマニュアルには、この項目が無いし、2.4.0同梱のドキュメントにもこの項目はないですが、mod_fastcgi.cには、ちゃんと実装されているようです。
- (但し、自分は使った事が無いので、何とも言えません‥…)
- SIGPIPEが流れる?
- Gauche-fastcgiでは、fastcgi.scmの中で、SIGPIPEハンドラ(fcgiループ開始部分に戻る)を設定してるので、大丈夫っぽいです。
- (fuyuki) v0.1のシグナル周りは手抜き心が爆裂してるので、あまり期待しないでください。というか、シグナルはFastCGIにとって本来的なものではないはずなので(リモートでも動くから)、あまり手をかけたくなかったんですっていう言い訳はSIGPIPEには通じないのか。しまった。
- SIGPIPE時の(fcgiループ中での)ターミネート処理等をちゃんとしたい場合は、自分でシグナルハンドラを上書きしましょう。
- ターミネート処理が必要になるのはfcgiループ実行時の中でも一部分だけだと思うので、with-signal-handlersが便利に使えるような気がします。
- (自分は昔、Perl?のFCGI.pmで、SIGPIPEで罠に引っかかったような気がするので…‥)
- ちなみに、普通のCGI?でも、SIGPIPEは素で流れた筈なので、トランザクションっぽい何かを操作するモノなら、ちゃんとシグナルハンドラを書かないと駄目です、本当は(でも、ちゃんと書いてる人は少ない気がする…‥)。
- 具体的には、プロセスが死んでも残るようなロック方式を使ってる場合とか(更に具体的に言うなら、ファイルやディレクトリやシンボリックリンクのような後に残るモノを使って実装されたロックを使っている場合。flock類はプロセスが死ぬとロックも消えるが…‥)。
- よく分からないけど、ごく稀に、500 internal server errorが起こる
- おそらく、コレが原因だと思う…‥(けど確証無し)
- 要するに、
- perl-5.6.1時点では、SIGTERMを受けると、プロセスはすぐに終了していた
- が、perl-5.8.3時点では、SIGTERMを受けても、すぐにはプロセスが終了せず、そのままコネクションを待ち受けたままになる
- 次にアクセスが来ると、そのプロセスが受けてしまう
- そして、この時点で、SIGTERMの処理が行われ、終了
- 結果として、0バイトのデータを返したのと同等となる
- incomplete headers扱いとなり、500になる
- と、いう事だと思う…‥(自信なし)
- ちなみに、SIGTERMが送られるのは、大体、並列同時アクセスが来て、fcgiプロセスが増えてから、片方が要らなくなった時に、送られる…‥筈。多分。
- この時の時系列順は、多分、こんな感じになると思う
- 並列同時アクセスが起こり、fcgiプロセスが二つになる
- しばらく、並列同時アクセスは起こらず、片方のプロセスは暇を持て余す
- 五分ぐらいして、mod_fastcgiのマネージャだか何だかが、片方のプロセスを不要だと判定して、SIGTERMを送る(しかし、すぐには死なず、そのまま残る)
- 並列同時アクセスが起こらない間は、片方しかリクエストを受けないので、問題なくアクセスが捌かれる
- しかし、次に並列同時アクセスが来ると、死に損ないプロセスがリクエストを受け、そのまま終了してしまい、500になる
- 尚、同じ問題は、Gauche?のGauche-fastcgiでも起こると思う。
- この問題を、ad hocに解決するならば…‥
- 適当に変数を一個用意。初期値は#f。
- SIGTERMハンドラを用意。中味は、上の変数を#tにして、割り込まれ元にそのまま戻るだけのもの。
- 毎回のFastCGIループの最後(次のリクエストを待ち受けるwaitに入る直前)で、上記変数が真ならexitするようにする
- で、いける筈…‥
- (勝手に追記) TERM を受け取ったとき、以下の動作が望まれているみたい。
- FCGI が次のリクエストサイクルを待っている時(acceptでblockしてるとき): 即座に終了する
- CGI のメインロジック中にいるとき: 全ての処理を終え、正しく応答を返してから終了する
代替。
http://fastcgi.coremail.cn/
最終更新 : 2005/11/16 05:24:27 JST