クラスタ構成の Tomcat をApacheでロードバランスする
戻る
動作環境

このページでは以下の環境での動作を説明しています。

  • Debian Linux Etch
  • Apache2.2.3
  • Tomcat5.5
  • J2SDK 5.0 Update10
ロードバランサの必要性

Tomcatでクラスタリングを行うことで、セッション情報の共有が行われます。これによって使用中のTomcatがダウンしても、別のTomcatに接続することでセッションを継続することができるはずです。しかし、これは現実的でありません。使用中のTomcatが動作を停止したとき、ユーザーはブラウザのURLを手で書き換えて稼働中のTomcatに明示的につなぎに行く必要があります。しかも、通常セッションIDはcookieに格納されています。これではURLが変更した場合セッションIDが取得できません。つまり、cookieが無効になっていてURLにセッションIDが組み込まれているときに、手作業でURLを書き換えることでしか、セッションを継続できません。そこで、Apacheをロードバランサとして使用することで、この問題を解決します。Apacheを中継することで接続先のURLはApacheのURLのみとなります。障害時にはApacheがTomcatサーバの死活を判断し、動作しているTomcatに処理を割り振ります。

mod_proxy_balancer

Tomcatのロードバランスには以下のモジュールを使用します。

  • mod_proxy
  • mod_proxy_ajp
  • mod_proxy_balancer

mod_proxyの設定はmod_proxy_ajp を使用して Apache と連携するを参考にしてください。ロードバランサの設定はproxy_ajp.confに記述することにします。

設定例 <IfModule mod_proxy_ajp.c> <IfModule mod_proxy_balancer.c> <Location /ClusterSample/> ProxyPass balancer://ClusterSample/ nofailover=Off </Location> <Proxy balancer://ClusterSample/> BalancerMember ajp://192.168.0.1:8009/ClusterSample/ loadfactor=10 BalancerMember ajp://192.168.0.2:8009/ClusterSample/ loadfactor=10 </Proxy> </IfModule> </IfModule>
StickySession

以上の設定でTomcatを動作させると、毎回アクセスするサーバーが変更されます。(JSPに各々サーバ名を記述するなどして、どのサーバを使用して表示されてるいるのかわかるようにしてみてください)しかし、最初に使用したサーバを使用し続け、障害時にのみ別のサーバに切り替わるようにしたい場合もあると思います。その場合はStickySessionを利用することで実現できます。

proxy_ajp.confに設定を追加します。

<IfModule mod_proxy_ajp.c> <IfModule mod_proxy_balancer.c> <Location /ClusterSample/> ProxyPass balancer://ClusterSample/ stickysession=JSESSIONID nofailover=Off </Location> <Proxy balancer://ClusterSample/> BalancerMember ajp://192.168.0.1:8009/ClusterSample/ loadfactor=10 route=jvm1 BalancerMember ajp://192.168.0.2:8009/ClusterSample/ loadfactor=10 route=jvm2 </Proxy> </IfModule> </IfModule>

stickysessionにJSESSIONIDを指定していますが、これはURLやcookie内のJSESSIONIDの後にピリオドを付加して、その後ろにrouteの文字列を付加することでサーバを割り振るための設定です。ここで注意すべきなのは、JSESSIONIDにrouteの文字列を付加するのはmod_proxy_balancerの仕事ではないということです。mod_proxy_balancerは文字列を読み取ってサーバを割り振ることだけしかしません。それではどのようにしてJSESSIONIDを加工するのでしょうか。実はTomcatにその設定があります。

1台目のserver.xmlの設定例 <!-- An Engine represents the entry point (within Catalina) that processes every request. The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host). --> <!-- You should set jvmRoute to support load-balancing via AJP ie : <Engine name="Standalone" defaultHost="localhost" jvmRoute="jvm1"> --> <!-- Define the top level container in our container hierarchy --> <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1"> <!-- The request dumper valve dumps useful debugging information about the request headers and cookies that were received, and the response headers and cookies that were sent, for all requests received by this instance of Tomcat. If you care only about requests to a
2台目のserver.xmlの設定例 <!-- An Engine represents the entry point (within Catalina) that processes every request. The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host). --> <!-- You should set jvmRoute to support load-balancing via AJP ie : <Engine name="Standalone" defaultHost="localhost" jvmRoute="jvm1"> --> <!-- Define the top level container in our container hierarchy --> <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm2"> <!-- The request dumper valve dumps useful debugging information about the request headers and cookies that were received, and the response headers and cookies that were sent, for all requests received by this instance of Tomcat. If you care only about requests to a

これで、JSESSIONIDの後ろに.jvm1もしくは.jvm2といった文字列が付加されるようになります。

StickySessionの問題点

StickySessionを利用する上で、困った問題があります。上記ではstickysession=JSESSIONIDのように設定していますが、文字列("JSESSIONID")の大文字小文字を区別してしまうのです。これがなぜ問題かというと、Tomcatでは普通、CookieにJSESSIONIDという名前の項目でセッションIDを保存します。しかし、Cookieが無効な場合URLにセッションIDを組み込むのですが、このときはjsessionidと小文字になってしまうのです。大文字のJSESSIONIDと小文字のjsessionid、両方に対応するような設定は現状では記述できませんので、どちらかをあきらめなければなりません。

*1 負け組SEの日常(http://makegumi.jp/blog/2007/06/mod_proxy_balancerstickysessio.html)様で、この問題に対応するパッチが公開されています。