Blog

PerlでTomcatのフリをしよう。Net::AJP13の巻

By Hiroyuki OYAMA Thu Jun 10 00:42:14 2004

WebサーバとTomcatを連携させるプロトコル"AJP13"を、ちょっとした出来心からPerlで実装してみました。というわけでPerlでServletコンテナのフリをする方法。意外にパフォーマンスもよさげ。

AJP13とは

JavaServletコンテナであるJakarta TomcatとApache HTTP Serverを連携させる場合、Apacheにmod_jkモジュール等を組み込んでリクエストをTomcatに転送する方法が広く利用されています。mod_jkとTomcatの間では何種類かのプロトコルを選択し利用することができ、今回ネタにしたAJP13もその一つです。
考え方は単純で、基本的には
  1. mod_jkはTomcatにSocketを貼る
  2. mod_jkはリクエスト情報をエンコードしてTomcatに送信する
  3. Tomcatは受け取ったリクエスト情報をデコードする
  4. Tomcatはリクエスト情報に基づいてServletを実行する
  5. Tomcatはレスポンス情報をエンコードしてmod_jkに送信する
  6. mod_jkは受け取ったレスポンス情報をデコードして、クライアントに送信する
といった流れになります。エンコードしたメッセージの形式についてはTomcatのAJPv13のページにやや詳しく書いてあります。内容がちょっと古いですが、概要を知る上では十分だと思います。
要はmod_jk(Apache)がクライアント、Tomcatがサーバという構成で、SocketはApacheのプロセス毎にConnect/Close(Half-close?)しています。

プロトコル自体は非常にシンプルだし、Apache以外のIISやiPlanetとかと繋げられるし、mod_jk側で複数のTomcatを束ねてロードバランスもできたりと結構便利な仕組みなのですが、Java以外で利用されている例は多くないようです。って僕が知らないだけかもしれないので情報キボン。

PerlでTomcatのフリをする

というわけで、ここ2日間の暇な時間(何パーセントが暇なのかは秘密だ)をつかってAJP13のサーバをPerlで実装してみました。
Net-AJP13-0.0.1.tar.gz
トータルで700行程度の小さなコードです。あ、βはおろかα以前のテスト的な実装なので、生暖かく見守っていただけると吉。ちなみにこのバージョンでは
use threads;
しているのでPerl 5.8.x系でthreadsが使える環境が必要です。

使い方はダウンロード後に解凍してmake; make installし、付属のajp13serverスクリプトを実行するだけです。
$ tar zxvf Net-AJP13-0.0.1.tar.gz
$ cd Net-AJP13-0.0.1/
$ perl Makefile.PL
$ make
$ perl -Mblib bin/ajp13server
終了はCTRL+C。デフォルトではlocalhostの8009/tcpでListenするので、必要であれば-pオプションでポート番号等を指定します。
$ perl -Mblib bin/ajp13server -p 8019
あとは、Apache側にmod_jkモジュールを組み込んでおいて、普通にTomcatに繋ぐときのようにpropertiesファイルを用意・JkWorkersFileディレクティブで読み込んであげるだけです。httpd.confの例としてこんな感じ。
<IfModule mod_jk.c>
    JkWorkersFile /path/to/jk.properties
    JkMount /perl-servlet/* perlworker
</IfModule>
jk.propertiesファイルの例としてはこんな感じ
worker.list=perlworker
worker.perlworker.port=8009
worker.perlworker.host=localhost
worker.perlworker.type=ajp13
設定が終わったらApacheを再起動して、ajp13serverも起動してみて設定したURLにアクセスしてみます。ちなみにmod_jkはリクエストが発生した時点でSocket貼りにいくし、失敗したら勝手にリトライするので、Apacheとajp13serverの起動の順番はあまり気にする必要は有りません。
 $ curl -i http://localhost/perl-servlet/default
モジュールの配布パッケージにサンプルとしておいてあるServletもどきは、webappディレクトリに置いてある2つだけ。
webapp/default.pm
webapp/benchmark.pm
コンテナ側でエラーレスポンスの処理をまったく実装していないので、受け付けられるリクエストはこの設定で
http://localhost/perl-servlet/default
http://localhost/perl-servlet/benchmark
の2つだけです。ちなみにURIとclassのマッピング時に
my $class = $r->{uri}. '.pm';
$class =~ s{/perl-servlet/}{./webapp/};
みたいなダサイことしているので、webappディレクトリと同じディレクトリでajp13serverスクリプトを起動する必要アリ。さらに上記の設定(JkMount /perl-servlet/*が重要)以外ではclassを見つけることができませんので注意。

制約事項と展望

ちなみにサーブレット等のAPIを決定するコンテナ部は差し替えられる作りなので、mod_perl互換やCGI互換のI/Fも作れるんだろうと思います。
今実装してあるデフォルトのコンテナは超ダサイ実装。リクエストに応じてwebapp/*.pmをロードして、do_get()をコールしているだけ。全然Servletっぽくないので、便利に使うには少なくともあともう一枚レイヤーが必要なようです。ちなみにSession等の仕組みもまだ実装していません。

走らせてみると判ると思うのですが、意外に良いパフォーマンスを見せてくれます。簡単なベンチマークでTomcat 5 + mod_jkの約80〜90%程度のパフォーマンスです。もちろんいろんな部分が簡素(手抜き)なままなおかげかもしれませんが、まだまだ改善の余地はありそうです。
ほんとに真面目に取りかかるかどうかはさておき、ToDoをまとめてみる。
  • Class Not Found etc...のエラーレスポンスの実装
  • もっとマトモなクラスローダ + コンテナの実装(なんでWEB-INFやweb.xmlみたいなクソ面倒くさい手続きが必要なのかなんとなく判った気がする)
  • mod_perl互換のコンテナの実装
  • CGI互換のコンテナの実装
  • 設定方法の決定(あたりまえですがXML禁止)
  • リスナー部の不足機能の実装とリファクタリング
  • パケット解析・組立処理のリファクタリング
  • ドキュメント作成
  • SourceForge.JPもしくはsourceforge.Netに置く
  • 仲間募集(これ大事)
  • プロジェクト名を決める(もっと大事)
こんなもんか? とりあえず興味ある方は宣伝&参加よろぴこです。
そーいやP5EEってどーなったんだろう。

Comments

Post a comment

Name:


URL:


Comments:


WebエンジニアのためのApacheモジュールプログラミングガイド

ApacheをHackする!
モジュールプログラミング強烈初体験!!
定価: 2,919円(税込)
ISBN: 4-7741-1799-4

hiroyuki_oyama IM status

Apache Users

Apache Modules

CPAN


Home > Blog > PerlでTomcatのフリをしよう。Net::AJP13の巻