(FreeBSD 7.3) ApacheとTomcatを手早く連携させる

先月この玄箱のwebサーバーが起動しなくなって、復旧に時間がかかると思ったので、PC上の仮想マシンにFreeBSD 7.3をインストールして、代替のwebサーバーを構築し始めた。
幸いにして玄箱がすぐに復旧したので、FreeBSDは中途半端な状態で放ったらかしたが、せっかくなので、予備のサーバーとして最後まで構築することにした。

今回のは、動けばいいだけの環境なので、手間がかからないよう、可能な限りportsを使わず、packagesで統一することに決めた。portsを使い出すと、依存するライブラリのバージョンがpackagesと合わなくなって、以後何もかもportsでインストールしないといけなくなる恐れがあるからである。

このサーバーの代替をするには、HTTPサーバーの機能とJava servletを動かす機能が必要である。そう決めた。TomcatはHTTPサーバーの機能も持つので、全てTomcatに任せるという手もあるのだが、TomcatはJavaで動いており、決して軽くない。当然、通常のHTTPリクエストはApacheで処理し、TomcatはJava servletやJSPを動かすのみとしたい。

ApacheとTomcatがそれぞれ別々のポート(80と8080とか)でリクエストを待つと、外部に2つのポートを公開しないといけないことになるし、アクセスURLにポート番号を含めることが必要になり、美しくないことになる。当然、Apacheが一旦全てのHTTPリクエストを受けて、必要なもののみTomcatに転送するようにしたい。

それは、Apacheのmod_proxyを使えば実現できる。このwebサーバーでもそうやっている。
FreeBSD 7.3のインストーラー(sysinstall)のパッケージ一覧でmod_proxyを検索すると、"mod_proxy_html"と"mod_proxy_xml"が見つかるが、どちらをインストールしてもmod_proxyはインストールされない。mod_proxyはApacheの本体と共に配布されているので、mod_proxyという名前のpackageが無ければ、どこかに含まれているとすればApache本体であるが、packagesのどのApacheをインストールしてもmod_proxyは入らない。従って、mod_proxyを使うにはそのようにオプションを設定してapacheをコンパイルするしか無いようである。セキュリティホールになり得るmod_proxyが不必要に有効にならないようにという配慮であろうか。

mod_proxyを使う以外に方法はあるのだろうか。Apacheから一部のリクエストをTomcatに転送する方法としては、次の3つの方法が一般的らしい。(参考:http://dev.ariel-networks.com/Members/inoue/tomcat-apache
・mod_proxy_http
・mod_proxy_ajp
・mod_jk
上の2つはFreeBSD7.3のpackagesには無いが、mod_jkはある。従って、mod_jkしか選択肢が無い。mod_jkも無ければApacheをコンパイルするしか無いと諦めがついたのだが、あるから仕方がない。mod_proxyが無いと、mod_perlを使うhttpdを別に動かして連携することができないが、仕方がない。packagesにmod_jkがあるので、この代替サーバーでのmod_perlの使用は諦める。

結局、以下の手順で、FreeBSD 7.3のpackagesだけでApache+Tomcatの連携ができるようになった。
1. packagesの一覧からmod_jk-ap2-1.2.30_1を選択してインストールする。
 apacheが入ってなければ、それも自動的にインストールされる。
2. Tomcatはpackagesに4.xも5.5も6.0もあるが、どれでも良いので、インストール動くようにしておく。
3. /usr/local/etc/apache2/のworkers.properties.sampleをコピーしてworkers.propertiesという名前にし、以下の行を書き換える。

worker.list=localhost
worker.jsp-hostname.port=8180
worker.jsp-hostname.host=localhost

4. 同ディレクトリのmod_jk.conf.sampleをIncludes/mod_jk.confとしてコピーし、JkWorkersFileの%%APACHEETCDIR%%の所とJkMountの行を書き換える。
JkWorkersFile /usr/local/etc/apache2/workers.properties
JkMount /*.jsp localhost
JkMount /servlet/* localhost
(以下略)

このようにしてApacheを再起動すると、httpdが受けたhttp://(hostname)/*.jspや
http://(hostname)/servlet/*にマッチするURLのリクエストがTomcatに転送されるようになった。


mod_proxy及びmod_perlの使用を諦めるまでに時間がかかったが、諦めた後は早かった。
意外と簡単でさくさく動いており、mod_jkにして正解だった。

しかし、sysinstallのpackagesのUIはもうちょっと使いやすくならないものだろうか。
ESCを押して出てくるウィンドウで検索してヒットしてもヒットした行に飛ばず、ヒットした行のみが表示される訳でもない。1つもヒットしなかったらエラーになるだけである。
先頭の文字を入力してもその文字で始まる行に移動しないので、ページ送りして所望のパッケージまで移動するしかない。ターミナルの設定の都合でPageUp/PageDownキーが効かないと大変である。
さらに、FreeBSD起動後にsysinstallコマンドでインストーラーを起動している場合は、依存するパッケージをインストールする途中でエラーになると、どのパッケージのインストールでエラーになったのかが表示されない(CD-ROM起動のインストーラーの場合はAlt+F2で見れる)。portsを使った後は、大抵、いずれかのライブラリのバージョン違いのためにエラーになるので、その頻度は決して低くない。pkg_addコマンドを使えばどれでエラーになったのかがわかるが、筆者は基本的にインストールCDを用意せずにネットワークインストールしているので、その時だけパッケージをダウンロードするのが面倒である。

筆者は、sysinstallのパッケージインストールでエラーになったら、pkg_addコマンドで詳細確認して、/var/db/pkgにシンボリックリンクを置いてpkg_addを騙し、sysinstallに戻ってインストールしているのだが、何かましな方法は無いものか。
今回FreeBSDをインストールし直しているのも、以前から使っているFreeBSDが、そんなことをしながらportupgradeを使いまくって、データベースが壊れてpkgdbでも直し切れなくなって、portsを使うのにも支障が出たからである。インストール時以外はpackagesを使うなということか。