Tomcat会话复制问题

时间:2016-10-07 10:42:15

标签: java session tomcat tomcat7 session-replication

TL; DR - 当主服务器发生故障时,sessionId中的节点名称未更新为备份中的当前节点名称。

Tomcat版本 - apache-tomcat-7.0.50

我设置了两个节点(我的应用程序在2个单独的tomcats中的2个实例),使用会话复制配置(也使用粘性会话).Below是来自server.xml的集群配置,它位于Engine标记内。它在两个节点中都类似,但端口号除外:

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8">
    <Manager className="org.apache.catalina.ha.session.DeltaManager"
    expireSessionsOnShutdown="false"
    notifyListenersOnReplication="true"/>

    <Channel className="org.apache.catalina.tribes.group.GroupChannel">
        <Membership     className="org.apache.catalina.tribes.membership.McastService"
        address="228.0.0.4"
        port="45564"
        frequency="500"
        dropTime="3000"/>
        <Receiver      className="org.apache.catalina.tribes.transport.nio.NioReceiver"
        address="auto"
        port="4050"
        autoBind="100"
        selectorTimeout="5000"
        maxThreads="6"/>

        <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
            <Transport     className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
        </Sender>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
        <Interceptor      className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
    <Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>\
</Channel>

<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>
<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>

在tomcat Manager中,我可以看到在登录时在主节点中创建了会话(例如:D042A0C5E380EB9E500224C87233119C.myNode1),并在备份中正确复制。

但是,一旦主节点出现故障,我希望备份节点中的sessionId能够使用当前节点名更新,即:D042A0C5E380EB9E500224C87233119C.myNode2

示例:

用户登录时:

Node 1 - Primary - jsessionIdSample.node1 
Node 2 - Backup - jsessionIdSample.node1 

当一个节点1停止时(预期)

Node 1 - - jsessionIdSample.node1 (NODE GOES DOWN) 
Node 2 - Primary - jsessionIdSample.node2 

但是发生了什么:

Node 1 - - jsessionIdSample.node1 (NODE DOWN) 
Node 2 - Backup - jsessionIdSample.node1

我有两个问题:

1)我的理解是,在主节点出现故障后,应该在备份中更新sessionID吗?我阅读了tomcat文档,它似乎应该。

2)如果它应该,请你帮我配置这个工作吗?我已经尝试过关于SO的其他问题的解决方案,但它们似乎都没有用。

编辑:根据建议添加完整的引擎配置:

节点1

    <Engine name="Catalina" defaultHost="localhost" jvmRoute="node1">
  <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster">
              <Manager className="org.apache.catalina.ha.session.DeltaManager"
               expireSessionsOnShutdown="false"
               notifyListenersOnReplication="true"/>

      <Channel className="org.apache.catalina.tribes.group.GroupChannel">
        <Membership className="org.apache.catalina.tribes.membership.McastService"
                    address="228.0.0.4"
                    port="45564"
                    frequency="500"
                    dropTime="3000"/>
        <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                  address="228.0.0.4"
                  port="4005"
                  autoBind="100"
                  selectorTimeout="5000"
                  maxThreads="6"/>

        <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
          <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
        </Sender>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
      </Channel>

      <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
             filter=""/>
      <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

      <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                tempDir="/tmp/war-temp/"
                deployDir="/tmp/war-deploy/"
                watchDir="/tmp/war-listen/"
                watchEnabled="false"/>
      <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
      <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
  </Cluster>

  <Realm className="org.apache.catalina.realm.LockOutRealm">
    <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
           resourceName="UserDatabase"/>
  </Realm>

  <Host name="localhost" appBase="webapps"
        unpackWARs="true" autoDeploy="true">
    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
           prefix="localhost_access_log." suffix=".txt"
           pattern="%h %l %u %t &quot;%r&quot; %s %b" />
  </Host>
</Engine>

节点2

    <Engine name="Catalina" defaultHost="localhost" jvmRoute="node2">
  <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster">
              <Manager className="org.apache.catalina.ha.session.DeltaManager"
               expireSessionsOnShutdown="false"
               notifyListenersOnReplication="true"/>

      <Channel className="org.apache.catalina.tribes.group.GroupChannel">
        <Membership className="org.apache.catalina.tribes.membership.McastService"
                    address="228.0.0.4"
                    port="45564"
                    frequency="500"
                    dropTime="3000"/>
        <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                  address="228.0.0.4"
                  port="4010"
                  autoBind="100"
                  selectorTimeout="5000"
                  maxThreads="6"/>

        <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
          <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
        </Sender>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
      </Channel>

      <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
             filter=""/>
      <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

      <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                tempDir="/tmp/war-temp/"
                deployDir="/tmp/war-deploy/"
                watchDir="/tmp/war-listen/"
                watchEnabled="false"/>
      <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
      <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
  </Cluster>

  <Realm className="org.apache.catalina.realm.LockOutRealm">
    <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
           resourceName="UserDatabase"/>
  </Realm>

  <Host name="localhost" appBase="webapps"
        unpackWARs="true" autoDeploy="true">
    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
           prefix="localhost_access_log." suffix=".txt"
           pattern="%h %l %u %t &quot;%r&quot; %s %b" />
  </Host>
</Engine>

提前致谢!

1 个答案:

答案 0 :(得分:1)

不确定您是否将某些东西混合在一起 - 例如你说

  

用户登录时:

Node 1 - Primary - jsessionIdSample.node1 
Node 2 - Backup -  jsessionIdSample.node1

节点2是否应使用以.node2结尾的会话ID?

使用恕我直言的会话ID来自jvmRoute中的<Engine>属性并粘贴到计算机上 - 当节点1配置为<Engine jvmRoute="node1">时,节点1是什么知道。很遗憾,您并未在上面引用您的引擎配置。

jvmRoute只是对负载均衡器的提示,即要路由到的机器,因此它必须稳定可靠。这可能很简单,只需额外增加 extra 确保您的Node 2配置了jvmRoute="node2"。我在tomcat中从未见过任何不同的行为。

即使在您对问题进行更新后,我感觉有些奇怪 - 请参阅我的答案中的引用部分,其中节点1和节点2都使用&#34; node1&#34;作为指标。那可能是罪魁祸首(或者是一个被遗忘的错字)。如果您正在使用Apache httpd,那么工作者必须像在workers.properties中的名字一样命名(至少它们必须是唯一的。请参阅cast