セッションレプリケーション問題

2010/06/24


seasar+sastrutsの環境でtomcatのセッションレプリケーションを使うと、
サーバが複数台ある時に問題が生じたので、その内容と対策を書く。

目標

 


上図のようなサーバ構成があるとする。
両方のサーバでセッションを共有させることで、
もし102,103のどちらかのサーバがダウンしたとしても問題なく動作させるようにする。

セッションが共有できていないと、
仮に102でセッションが作られたユーザは、
103サーバにリクエストが送られた途端にセッション情報がないのでエラーになってしまう。

問題

本番反映時にセッションレプリケーションの動作確認を行ってみたら、
ページを読み込むたびに「表示」→「エラー」を繰り返していた。
次に102,103のログを見ながらページを読み込むと、
ある特定のサーバへのリクエストのみエラーが起こっていて、
正常にセッションレプリケーションができていないのではないかと推測。

調査を行うと、sastrutsのアノテーションを利用して、
必要な情報を格納するDTOクラスをセッションに登録した場合には、
tomcatのセッションレプリケーションができないということがわかった。
http://ml.seasar.org/archives/seasar-user/2009-July/017893.html

@Component(instance = InstanceType.SESSION) //←コイツ
public class SampleDto implements Serializable {

    private static final long serialVersionUID = 1L;

    public String name;
}

対策

対策は以下の参考URLにあるように2つあるのだけど、

今回はsetAttributeする方法を取った。
RequestUtil.getRequest().getSession().setAttribute("sampleDto", sampleDto);

この対応で本番環境でもセッションレプリケーションが実現できた!!

※開発段階でサーバを2台用意しセッションレプリケーションのテストができる状態にできるのであれば、
事前に確認してリスクを軽減でき、本番でセッションレプリケーションの問題が生じたときにも調査が容易になる。
 

備考

ついでにtomcatのセッションレプリケーションの設定方法も書く

・httpd.conf
<Proxy balancer://cluster/>
    BalancerMember ajp://xxx.xxx.xxx.xxx:8009 route=MAP1 loadfactor=10 keepalive=on
    BalancerMember ajp://xxx.xxx.xxx.xxx:8009 route=MAP2 loadfactor=10 keepalive=on
</Proxy>

・server.xml
/*以下は192.168.0.102の設定。192.168.0.103はjvmRoute=MAP2, tcpListenAddress=192.168.0.103とする。*/
<Engine name="Catalina" defaultHost="localhost" jvmRoute="MAP1">
  <Host name="localhost" appBase="webapps" />
  <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
        managerClassName="org.apache.catalina.ha.session.DeltaManager"
        expireSessionsOnShutdown="false"
        useDirtyFlag="true"
        printToScreen="true">
  <Membership className="org.apache.catalina.ha.mcast.McastService"
        mcastAddr="228.0.0.4" mcastPort="45564" mcastFrequency="500" mcastDropTime="3000"/>
  <Receiver className="org.apache.catalina.ha.tcp.ReplicationListener"
        tcpListenAddress="192.168.0.102" tcpListenPort="4001" tcpSelectorTimeout="100"
        tcpThreadCount="2"/>
  <Sender className="org.apache.catalina.ha.tcp.ReplicationTransmitter"
        replicationMode="pooled"/>
  <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
        filter=".*\.gif;.*\.js;.*\.jpg;.*\.htm;.*\.html;.*\.txt;.*\.xhtml"/>
  <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
        tempDir="/tmp/war-temp/"  deployDir="/tmp/war-deploy/"  watchDir="/tmp/war-listen/"
        watchEnabled="false"/>         
  </Cluster>
</Engine>

・web.xml
<!-- Session Clustering -->
<distributable />

0 コメント:

コメントを投稿