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 />