Apache 2.2.x と Tomcat の連携(1) ~mod_proxy_ajp の利用~

Apache 2.2.x と Tomcat 6.0.x/Tomcat 7.0.x を mod_proxy_ajp を利用して連携するとき、以前の設定をコピーしたり知っているはずのことを調べたりしてしまうので、メモとして残すことにした。環境は、Cent OS 6.4 と、Apache Tomcatからダウンロードしてインストールした Tomcat 6.0.x/Tomcat 7.0.x を想定している。テストした Apache のバージョンは、2.2.15だ。

必要なモジュール

mod_proxy と mod_proxy_ajp が必要になる。httpd.conf もしくは httpd.conf がインクルードする設定ファイルに、以下の記述が必要だ。

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

コンテキストパスと URL が一致する場合

最も単純なのは、Apache の URL のパスと Tomcat のコンテキストパスが同一の場合である。具体的な例を挙げると Tomcat のコンテキストパスが「/app」で、Apache と連携したときに「http://192.168.1.1/app」でアクセスできるようにする場合である。

コンテキストパスと URL が一致する場合は、単純に ProxyPass を設定するだけでよい。以下は、Apache が192.168.1.1で Tomcat が192.168.1.2で動作しており、http://192.168.1.1/app でアクセスできるようにする場合の例である。

ProxyPass /app ajp://192.168.1.2:8009/app
<Location /app>
...
</Location>

余談だが、Apache の<Directory>ディレクティブはファイルシステムの物理パスに対するアクセスを行った場合に適用されるため、ProxyPass で設定した URL へのアクセスを制御する場合は<Location>ディレクティブを使用する。

コンテキストパスと URL のパスが異なる場合

コンテキストパスと URL が異なる場合、以下の2つの問題が発生する。

  1. HttpServletResponse.sendRedirect() メソッドを利用したとき、コンテキストパスと URL のパスが異なるため、クライアントは(おそらく)ページを見つけられない
  2. Tomcat が発行したセッション用のクッキー(通常はJSESSIONID)は Path に Tomcat のコンテキストパスが入っているため、セッションを維持できない

わかりにくいので、具体例を挙げていく。URL はドメインのトップにしたいが、アプリケーションは app.war という名前でデプロイすると、一般的に以下の状態になる。

  • コンテキストパス : /app
  • URL : http://192.168.1.1/

1番目の問題から考えてみる。アプリケーション内でブラウザーにトップページにリダイレクトさせるために、

HttpServletResponse response; // どこかから渡された response
response.sendRedirect("index.jsp");

というコードを書くとする。プログラマーが意図しているのは、「Location:http://192.168.123.2/index.jsp」というヘッダーが送出されることだが、実際には現在のリクエスト URI からの相対表記、もしくはコンテナからの相対表記であると識別される。従って相対 URL で指定するとコンテキストパスがついた URL、たとえば「Location:http://192.168.123.2/app/index.jsp」というヘッダーを送出する。これを修正してくれるのが、「ProxyPassReverse」ディレクティブだ。今回の例では、以下のように記述する。

ProxyPass / ajp://192.168.1.2:8009/app
ProxyPassReverse / http://192.168.1.1/app

Apache のドキュメントに記述があるとおり、ProxyPass を利用している URL に関連するリダイレクトがヘッダーに含まれる場合、ProxyPassReverse は「http://192.168.1.1/app」へのリダイレクトを「http://192.168.1.1/」に変換する。

2番目の問題は、Tomcat が発行する JSESSIONID のクッキーに含まれる Path の問題だ。ブラウザーは、クッキーに設定されたドメインやパスを見て、クッキーを送出すべきか判断する。今回の例では、Tomcat
は「Set-Cookie:JSESSIONID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; Path=/app/」というヘッダーを出力するだろう。しかしブラウザーがアクセスする URL は「http://192.168.1.1/」でパスは「/」、クッキーのパスと URL のパスが一致しないのでクッキーを送出しない。Tomcat はクッキーの値を取得できないため、セッションを維持できない。これを修正してくれるのが、「ProxyPassReverseCookiePath」ディレクティブだ。今回の例では、以下のように記述する。

ProxyPass / ajp://192.168.1.2:8009/app
ProxyPassReverse / http://192.168.1.1/app
ProxyPassReverseCookiePath /app /

Apache のドキュメントに記述があるとおり、Set-Cookie ヘッダ内の path 文字列を書き換えてくれる。

Apache には ProxyPassReverseCookieDomain ディレクティブも用意されており、クッキーのドメイン文字列を調整してくれる。今回の環境では、Tomcat から送出されたクッキーに Domain の指定はなかった(この場合同一ドメインのみ許可する)ので、ProxyPassReverseCookieDomain ディレクティブは使っていない。クッキーに Domain の指定が含まれる場合は、ProxyPassReverseCookieDomain ディレクティブを使う必要があるかもしれない。


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Time limit is exhausted. Please reload CAPTCHA.