mod_perl 2.0 の Server Life Cycle

mod_perl 2.0 のサーバ起動にまつわる文書を読み込んでいました。

  • サーバスタートアップスクリプトは,1.0 時代のドキュメントでは「PerlRequire」記述子で読み込むように書かれていることが多いが,実行される時点が中途半端。なので,PerlPostConfigRequire を使う方が吉。もし設定ファイル自体で Perl の機能を利用しているのであれば(普通そこまでコアなことやらなくて済むんだけど),PerlConfigRequire を使うとサーバ設定フェイズ(すなわちかなり早い段階)で実行される。
  • Apache 2.x では,graceful restart がうまくいくことの確証を得るために,一度サーバ設定フェイズが終わると,Apache 自身を再起動する。ということは,サーバ起動時に,スタートアップスクリプト等は 2 回実行される。このことで困るってことはたいていないんだけど,スタートアップスクリプトでログ吐きとかやってるとあれれ?と思うかも。
  • かくなるように,スタートアップスクリプトは基本的にマスタサーバプロセスの起動時,再起動時にしか実行されない(と思う)。どういうことかというと,MaxRequestsPerChild を超えたために子プロセス等が再起動した場合でも実行はされない(と解釈しました)。
  • だから,プロダクションサーバ等で DBIx::Class::Schema を継承したクラスみたいに重い*1モジュールはスタートアップスクリプトのほうで読み込んでおくとよい,と,思,い,ます。


おまけで,中途半端ながら上記文書の「mod_perl Startup」節の抄訳をあげておきます。今回は全然推敲してないです。

mod_perl Startup

以下の節では mod_perl のスタートアップについて詳述します。

起動直後の再起動

Server Life Cycle 節で述べたように,Apache は起動時にサーバ設定フェイズに移行し,次に PerlOpenLogsHandler フェイズに移行,そして PerlPostConfigHandler フェイズに移行した後に,すぐに自分自身を再起動します。ですから,サーバスタートアップで行われるすべての挙動は二度実行されます。Apache の再起動によって,Perl エンジンは完全に終了し,再びスタートします。

Perl エンジンはいつスタートするのか

Apache を 'httpd -t' (これは 'apachectl configtest' するのと同じ意味です)あるいは 'httpd -S' (訳注: 解釈後の設定ファイルのダンプ;現状だと VirtualHost 部分だけ)というコマンドラインで起動したとき,サーバ設定フェイズのみ実行し,終了します。設定ファイルによっては,Perl エンジンが起動することもありますし,しないこともありえます。詳しくは以下をご覧下さい。

通常のスタートアップでは,mod_perl 2.0 では Perl エンジンの始動をサーバ設定フェイズが終了するまで遅らせます。これは PerlSwitch 記述子を利用できるようにするためです。Perl エンジンが始動した後ではもう Perl のスイッチを設定できませんから。

サーバ設定フェイズが終了すると,mod_perl は post_config フェイズ の一番最初で Perl エンジンを起動し,登録されたすべての PerlRequire エントリと PerlModule エントリを実行します。

post_config フェイズの終了間際で,PerlPostConfigRequire エントリを実行します。

サーバ設定フェイズのあいだに下記の記述子に遭遇した場合,mod_perl 2.0 はただちに Perl エンジンを起動します(これらの記述子では Perl が起動している必要があるので)。

  • PerlLoadModule
  • <Perl> セクション
  • PerlConfigRequire

ですから,Perl エンジンをできるだけ速く起動したいのであれば,httpd.conf に空の <Perl> セクションを記述すればできます。

<Perl>
# この記述しによって Perl エンジンは通常より早めに起動します
</Perl>

という記述を DSO 版の mod_perl を使っているのであれば LoadModule した直後に,static 版の mod_perl を使っているのであれば mod_perl の設定が書かれているより前に,加えてください。ですが,ほとんどの場合,かわりに PerlConfigRequire 記述子を使うことになると思います。

スタートアップファイル

サーバ起動時に PerlPostConfigRequire 記述子を使って,スタートアップ用 Perl スクリプトを実行できます。たとえば,

PerlPostConfigRequire /home/httpd/Perl/lib/startup.pl

のように。

このスタートアップスクリプトは,Perl モジュールの検索パス(@INC)を設定したり,よく使われるモジュールをプリロードしたり,よく使われる定数をプリコンパイルしたり,などのために使うことができます。典型的な mod_perl 2.0 用のstartup.pl ファイルの例を示します。

省略(http://perl.apache.org/docs/2.0/user/handlers/server.html 参照)

このファイル例では,まず,非標準のディレクトリを Perl モジュール検索パス @INC に追加しています。

use lib qw(/home/httpd/perl);

もし mod_perl 1.0 との互換レイヤが必要なら下記のように,該当部分のコメントをはずしてください。

use Apache2::compat ();

次によく使う mod_perl 2.0 のモジュールと定数をプリロードしています。

最後に,一般のモジュールと同じように startup.pl ファイルはステータス 1 で終了しなくてはいけません。

リスタートに対処する

サーバのスタートアップで実行される Perl モジュール / スクリプトは,理想を言うと Apache の自動再起動に影響をうけないものである必要があります(訳注: スタートアップスクリプトがサーバ起動時に一度だけしか実行されないと思いこんだコーディングをしないほうがよい,ということ)。しかしながら,再起動問題に対処したい場合には,Apache2::ServerUtil::restart_count を使うことができます。

*1:いやほんとに重いですね。プロファイリングしたところ Class::C3 のせいっぽい。ということは Perl 6 になると改善されるのでしょうか。