PHP温故知新 − PHPはバッチ処理ができなかった(その2)
(前回からの続き) では昔のPHPはなぜバッチ処理ができなかった(やりづらかった)のだろうか? 実は、PHP言語の動作原理そのものに原因がある。
PHP言語で書かれたプログラムを実行する方式はいろいろある(後述)のだが、 もっとも多く用いられている方法は、PHPの実行エンジンをApacheのモジュールとして稼動させるというものだ。 これは一般にDSOコンパイル方式などと呼ばれる(DSO=Dynamic Shared Object)。 以下の説明ではWebサーバとしてもっとも一般的なApacheを前提として話を進めるが、 ほかのWebサーバ(IISなど)であっても基本は似たようなものだ。
上の図はApacheの構造をものすごく簡単に示したものだ。 このように、Apacheの内部は機能ごとにいくつかのモジュールに わかれており、必要に応じてモジュールを開発し、追加/変更することができる。 ちなみに、上にある各モジュールはなにかというと、
| mod_log_config | Apacheのログのフォーマットをつかさどる。 httpd.confファイルで言えば"LogFormat"という設定値にあわせて 実際にログをファイルに書き込む機能。デフォルトでコンパイル/追加される。 |
| mod_access | アクセス制限をつかさどる。 httpd.confで言えば"Deny"とか"Allow"とかそういうやつ。デフォルトでコンパイル/追加される。 |
| mod_auth | 基本認証機能を提供する。認証のかかったページを見ようとすると ブラウザがポンと認証用ダイアログボックスを示すアレ。デフォルトでコンパイル/追加される。 |
| mod_php4 | PHP実行エンジン。HTML中に埋め込まれた <?php 〜 ?>という タグ間に書かれたPHPコードを実際に実行し、結果をApacheに返す。 Apacheはそれをユーザーのブラウザに返す。 |
さて、わざわざ、PHPの動作原理などと難しい話をしたのにはもちろん理由がある。
前回、Webシステムの機能は画面処理とバッチ処理の 大きく二つにわかれるということを述べた。当然、PHP言語で書かれた画面処理は、 上で述べたようなApacheに追加されるmod_php4モジュールがそれを実行してくれる。 しかしバッチ処理はどうだろう?
画面を見る(ブラウザでアクセスする)or画面上のボタンを押す = Apacheがそれを受け取って処理してくれるというわけだが、画面を見るわけでもボタンを押すわけでもないバッチ処理において、 Apacheはどう対処するのか?どうしようもないのだ! Apacheは、ブラウザからのなんらかのアクセスがないと何もできない。 不思議なことではない。一般にWebサーバーとはそういうものだ。 そのため、Apacheに依存するPHP実行エンジンは画面処理しかできない! ということになる。
対処方法はいくつかあるが、いずれもトリッキーというか、スマートではない。
-
バッチ処理を画面処理として走らせる
バッチ処理としての機能だけで、画面としてはほとんど何のHTML出力もしない PHPコードを書き、それをApache上に置く。 そしてほかのサーバー上で、あるいはWebサーバそのもの上で、 lynxやwgetといったコマンドラインから実行できるようなテキストブラウザ (Mozzilaでもできるのかな?)をcronなどで定期実行し、 その画面にHTTPアクセスさせることで、バッチ処理を走らせる。- この方法だと、たとえばアクセスが多くて 画面処理がこみあっている場合、バッチ処理用画面へのアクセスもその混雑に巻き込まれてしまい、 結果的にバッチ処理をうまく実行できない事態に陥る可能性がある。 オークションサイトで言えば、 オークション終了時刻の間際に出品者や入札者のアクセスが 増加したためにオークション終了バッチ処理が動かなくなるなんてことになる。 それはまずいだろう。
- 10分とか20分といった時間のかかる大きなバッチ処理の場合、 Apacheのタイムアウト制限に引っかかってバッチ処理が完全に終わってないのに前に 強制的にPHPスクリプトが終了させられてしまう可能性すらある。
-
ほかの画面処理のついでにバッチ処理を走らせる
上で述べた方法とほとんど同じ。 実はPHP自身もこの方法を使ってある処理を行っている。 それは古いセッション保存用ファイルの削除という処理だ。 通常、session_start()関数が呼ばれるたびに 1/100の確率でこの処理も勝手に走るようになっている。 詳しくはここを。 -
CGIコンパイル版PHPエンジンを併用する
PHPスクリプト実行エンジンにはいくつかのコンパイル方式がある。 Apache-DSO方式のPHPが、完全にApacheの機能の一部として(=Apacheに依存して) 動作するのに対し、CGI方式でコンパイルされたPHP実行エンジンは apacheとは無関係に単体で動くこともできるので、バッチ処理に向いている。 ただしCGI方式だと画面処理はApache-DSO方式と比べ格段に遅くなってしまう。 画面処理用にApache-DSO方式のPHPエンジンを、バッチ処理用にCGI版を、 という使い分けをする方法もあるが、 二つのPHPエンジンを同時に管理しなければならなくなり、面倒だ。
この問題をながらく抱えていたPHPだが、 2002年12月にリリースされたPHP4.3.0によって、改善された。
PHP実行エンジンをコンパイル/インストールすると、 CLI(Command Line Interface)というコマンドラインから実行するためのインターフェースも デフォルトでインストールされるようになったのだ。 CLIは例えば /usr/local/bin/php といった具合で実行コマンドとして インストールされる。/usr/bin/perl と似たようなものだ。 これにより、画面処理は通常通り、Apache-DSO版で実行し、 バッチ処理はCLIにやらせる、といったことが完全にサポートされるようになった。
たとえば掲示板のように、書きこむ、消す、修正する、 といった程度の機能であれば、画面処理だけですべて事足りるので バッチ処理ができないという問題を気にする必要もなかった。 だが、ちょっと高機能なWebサイトをつくるにはバッチ処理が欠かせず、 しかしPHPはそれに答えることが事実上困難だった。 解決策を開発してくれたPHP開発コミュニティの皆さんに敬意を表したい。

コメントする
(初めてのコメントの時は、コメントが表示されるためにこのブログのオーナーの承認が必要になることがあります。承認されるまでコメントは表示されませんのでしばらくお待ちください)