MovableType3.35をmod_perlで動かす(2/2)

前のエントリーに書いたように、mod_perlのApache::Registryを使ってMovableTypeを動かすのに失敗した後、改めてMovableType3.2のマニュアルを基点に調べていると、MovableType DocumentationのページMovableType3.3のインストールガイド(PDF)にもmod_perl化の方法が書かれていることに気付いた。こちらにはApache::Registryを使う方法は書かれていない。

そこでMovableType3.3のインストールガイドに従ってやってみた所、いくつかのトラブルがあったが、何とかMovableTypeをmod_perlで動かすことができた。


●mod_perlの設定(MovableType自体をPerlHandlerにする)
最終的にhttp.confの末尾に書いた設定は以下の通り。/path/to/...となっている部分は、実際のものから書き換えている。

#(a) library path descriptions passed as-is to the Perl interpreter
<Perl>
use lib '/path/to/mt/lib';
use lib '/path/to/mt/extlib';
use lib '/path/to/mt/plugins/WidgetManager/lib';
use lib '/path/to/mt/plugins/StyleCatcher/lib';
use lib '/path/to/mt/plugins/GoogleSearch/lib';
use lib '/path/to/mt/plugins/spamlookup/lib';
</Perl>

#(b) just as the installation guide says
Alias /mt/mt-static/ /path/to/mt-static/

#(c) definition of the Perl handler, set to MovableType
PerlModule MT::App::CMS
<Location /mt/app>
SetHandler perl-script
PerlHandler MT::App::CMS
PerlSetVar MTConfig /path/to/mt/mt-config.cgi
Allow from 192.168
</Location>

#(d) corresponding to "$CGIPath/$AdminScript" in mt-config.cgi
<Location /cgi-bin/mt/mt/app>
SetHandler perl-script
PerlHandler MT::App::CMS
PerlSetVar MTConfig /path/to/mt/mt-config.cgi
Allow from 192.168
</Location>
(a)のPerlのライブラリパス設定の部分は、インストールガイドには最初の2行しか書かれていないが、実際にはインストールしてるプラグイン全ての分が必要だ。プラグインの分の設定が無いと、MovableTypeの管理画面で時々、例えば下のようなエラーが出る。
Can't locate object method "get_handle" via package "StyleCatcher::L10N" at /usr/local/www/cgi-bin/mt/lib/MT/Plugin.pm line 459.

(b)の部分はインストールガイドのままの記述だ。おそらくhttpd.conf内のaliasが誤って適用されないようにするための処置だと思われ、必須ではないような気がするが、念の為加えている。

(d)の部分は後述の"$CGIPath/$AdminScript"の対策だ。


●mt-config.cgiの設定
インストールガイドに書かれている通り、下の設定を加える。

StaticWebPath http://hostname/mt/mt-static
AdminScript mt/app
StaticWebPathのhostnameより右の部分は、httpd.confの(b)で定義したエイリアスにする。実際には、StaticWebPathは既存の設定のままでも、少し使った感じでは問題なく動いたように見えた。


●起動確認
さて、インストールガイドに従ってhttpd.confとmt-config.cgiを書き換えてhttpdを再起動し、いざmod_perl経由のMovableTypeの管理画面にアクセスしようとすると、URLがわからない。もちろん既存のURLにアクセスすると、別プロセスのPerlのCGIが起動してしまう。上記の設定の場合、正解は、

http://hostname/mt/app
だ。なぜインストールガイドに書かれてないのだろう。httpd.confをいじるなら、それくらい判れということだろうか。

当初、上記(d)の設定をしていない状態で、ブラウザでhttp://hostname/mt/appにアクセスするとログイン画面が表示され、パスワードを入力すると、mt-config.cgiのCGIPATHとAdminScriptとを繋げたURL(http://hostname/.../mt/mt/appのような感じ)にジャンプしてしまい、ページが見つからないというエラーになってしまった。
それで思わずCGIPATHをhttp://hostname/に書き換えてしまった。それから出てくるエラー(プラグインが見つからないというエラーもここで出た)に対処すると、そこそこ動作するようになった。エントリーの追加、サイトの再構築もできたので、これでバッチリかと思い始めた頃、コメントの投稿ができないことに気付いた。CGIPATHを書き換えてしまったため、MovableTypeが生成したページから呼ばれる他のCGIが起動できないのだ。

正直な所、この管理画面のURLが"$CGIPATH/$AdminScript"になる問題への適切な対処はわからない。
インストールガイドに書かれてる方法で、必要な全てのCGIをmod_perl化すれば良いかも知れないが、そうするとテンプレートに書いている全てのCGIへのリンクをmod_perlのものに書き換えないといけなくなるので大変だ。
という訳で、上記(d)の設定を加えて、$CGIPATHと$AdminScriptとを繋げたURLについても/mt/appと同じ動作をするようにした。もしかして、インストールガイドの<Location /mt/app>は、CGIPATHのホスト名より下の部分を付け加えたものとして読めということだろうか。


●検索機能(mt-search.cgi)のmod_perl化
インストールガイドには、同様の方法でMovableTypeのどのCGIもmod_perl化できると書かれており、このサーバーではmt-search.cgiが非常に遅く、サイト内の検索に1分くらいかかっていたので、これをmod_perl化することにした。

httpd.confに追加する必要があるのは、PerlModuleの行と、それに続く<Location>のブロックだ。インストールガイドでMT::App::CMSとなっている部分(アプリ起動メソッド)を何にすべきかは、mt-search.cgiの中身を見ればわかる。

use MT::Bootstrap App => 'MT::App::Search';
とあるので、MT::App::Searchだ。従って、
PerlModule MT::App::Search
<Location /mt/search>
SetHandler perl-script
PerlHandler MT::App::Search
PerlSetVar MTConfig /path/to/mt/mt-config.cgi
</Location>
というのをhttpd.confの末尾に追加し、httpdを再起動した。
それから、MovableTypeの検索機能のURLがhttp://hostname/mt/searchに変わったので、テンプレート内のmt-search.cgiの部分を書き換えて、ページを再構築した。
以上の手順で、検索機能をmod_perlで起動することができるようになった。

ただ、httpd起動直後は、なぜか検索を実行するとノータイムでエラーとなってしまい、何回か検索を実行しないと初回の検索がなされない。httpdのログに何も出ないし、ブラウザの画面には「エラーが発生しました」とだけ出るので、何が悪いのかさっぱり分からない。

ついでに、テンプレートを全て書き換えるのが大変なので、httpd.confの上記の<Location>ブロックの直後に

<Location /cgi-bin/mt/mt-search.cgi>
SetHandler perl-script
PerlHandler MT::App::Search
PerlSetVar MTConfig /path/to/mt/mt-config.cgi
</Location>
を加えてみた所、自信は無いが、とりあえず以前のCGI起動のURLでもmod_perl起動するようになった。


●その他の設定
mod_perlでPerlを常駐化すると、httpdの子プロセスのそれぞれにPerlが常駐することがわかった。
MovableType常駐後は子httpd1つ当たり約30Mものメモリを占有してしまう。swapと合わせてもメモリが192Mしかないこのサーバーでは空きメモリがあっという間に無くなってしまったので、子httpdの数、すなわちhttpd.confのMaxClientの数を減らした。


●効果と課題
MovableTypeのmod_perl化により、MySQL導入後も最低13秒かかっていた、サーバー側の処理が発生する管理画面の操作は、速い時は4秒で終わるようになった。実に快適になった。また、1分かかっていたサイト内のテキスト検索は、15秒以下で終わるようになった。

但し、httpdの子プロセス1つ1つが大量のメモリを消費するようになったため、httpd.conのMaxClient(サーバーへの最大接続数)を極めて少ない数にせざるを得なくなってしまった。何かメモリを節約するいい方法が無いと、mod_perlは低スペックのサーバーではあまり使えない。
例えば、ポート待ち受けのhttpdが子プロセスでなくスレッドで動いてくれると、メモリが大幅に節約されると思われるが、そのようにできるのだろうか。または、1つか2つの子httpdしかmod_perlが使えないような設定ができないものか。

それから、MovableTypeの管理画面を短時間に連続で操作している間も、ログイン画面が何度も出てしまうようになってしまった。子httpdプロセス間でセッション情報が同期されないため、子httpdプロセスの数(httpd.confのMaxClientの数)だけ出るということだろうか。もしそうならMovableTypeの問題だ。せっかくApache::Cookieをインストールしたのに、何とかならないものか。


●その他
今回、コメントとトラックバックのCGI(mt-comments.cgi, mt-tb.cgi)のmod_perl化は省略した。検索機能をmod_perl化すると動作が不安定になったのでやめたのだが、もう1つの理由は、これらを高速化すると、スパムを受けた時の被害が拡大する恐れがあるからだ。

今回の取り組みの中で、興味深いページを見つけたので、記しておく。特にPerlの肩を持つ訳ではないが、真実とはこういうものだ、という感じがしないだろうか。
JavaはPerlよりも比較にならないほど速い?
PerlよりPHPの方が軽くて速いは本当?