Tomcatクラスタの落とし穴?
2007.10.17 Wednesday てっく 00:58 comments(0) trackbacks(0) by nyoshikimi
先日から仕事でTomcatのクラスタ機能の検証を行っていました。
単なる機能検証ではなく、昨年度から炎上しているプロジェクトでクラスタリングしているにもかかわらず、フェイルオーバー時にセッションが引き継がれない現象が起きているから、なんとかしてくれというのがミッションの内容。少し前までは、こういった、込み入った事情がある検証は、優れた技術力を持った人が対応しいたのですが、会社の事情により、(入れ替わり立ち代わりの多い業界ですので。。。)私のような未熟者が対応する事になりました。
かれこれ、半年前から起きているらしく、何度か検証はしているものの、一向に解決のめどが見えないとの事で、設定やTomcatの再起動手順に問題ないか調べる事から始まりました。かなり、右往左往しましたが、結果から行くと、Tomcatインストール時に作成されるクラスタリングの設定サンプル(server.xmlでコメントアウトされている部分)の設定で何の問題も無いです。ただし、差分レプリケーション(DeltaManager)の場合(一般的な設定)、プログラミングで注意が必要です。
セッションに格納(setAttribute)するオブジェクトに変更を加えた時には、必ず、再度setAttributeをコールしてオブジェクトの置き換えを行う必要があります。通常、シングル構成の場合、一度セッションに格納したオブジェクトを次回以降のリクエストで変更を加えても、再度、セッションに格納し直す必要はありません。これは、Javaのオブジェクトが参照型であるためです。あくまでも、セッションに格納されたオブジェクトは、実態があるメモリのアドレスが格納されるだけです。セッションに格納されたオブジェクトに変更を加えた場合、実態のほうのデータが更新されます。すでに、オブジェクトはセッションに格納されている(HttpSessionから参照されている)ため、レスポンスをブラウザに返した後も、ヒープ上にオブジェクトが存在し続けます。この辺は、Javaプログラマーの試験でよく出題されると思います。で、落とし穴ですが、差分レプリケーションをしている場合、差分情報(Delta)のみが相手のTomcatに渡されます。この「差分」は、変更を加えたデータが必ず送られるわけではなく、明示的にsetAttribute(remobeAttribute)されたオブジェクトのみ送られるのがポイントです。
「フェイルオーバーするとき以外は、セッション情報が正常に保たれているのでソースコードには問題ない」という前提で検証を行っていたため、この答えにたどり着くまでにかなり苦労しました。
実際にTomcatのソースをローカルにダウンロードして、ソースを確認したり、Tomcatのホームページの変更履歴(Change Log)に似たような変更点はないか調べたり、Apacheのメーリングリストを検索しまくったりとか、かなり遠回りして答えにたどり着きました。なんだよ。。。アプリのバグじゃん。。。
おかげでというのもなんですが、WEB上に情報がほとんどない全データレプリケーション(SimpleTcpReplicationManager)を試してみたり、(実際にソースコードも見てみました。)レアな設定値(ソースを展開すると、全パラメータをまとめたxmlファイルがあります。)を試したりと、遊び心のある検証でしたが。。。
他に、mod_jk側でsticky_session=1にしてもJSESSIONIDのworkerと異なるworkerと通信してしまう現象なんかも確認できたりしました。ちゃんと対処法も見つけています。その件は、また、後ほど。
最終更新:2011年01月13日 21:59