wake-up-neo.com

Die Cluster-/Sitzungsreplikation von Tomcat wird nicht ordnungsgemäß repliziert

Ich stelle Clustering/Replication auf Tomcat 7 auf meinem lokalen Computer ein, um es für die Verwendung mit meiner Umgebung/Codebase auszuwerten.

Konfiguration

Ich habe zwei identische Tomcat-Server in gleichrangigen Verzeichnissen, die an verschiedenen Ports laufen. Ich habe httpd an zwei anderen Ports abgehört und mich als VirtualHosts mit den beiden Tomcat-Instanzen verbunden. Ich kann über die konfigurierten Ports auf beide Umgebungen zugreifen und mit ihnen interagieren. alles funktioniert wie erwartet.

Auf den Tomcat-Servern ist das Clustering in server.xml folgendermaßen aktiviert:

   <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="4001"
                  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>

und ich habe den vertreibbaren Tag ganz am Anfang von web.xml hinzugefügt:

<web-app xmlns="http://Java.Sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://Java.Sun.com/xml/ns/javaee
                      http://Java.Sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0">
  <distributable />

  (lots more...)

</web-app>

Was funktioniert

Wenn die Server starten, werden sie protokolliert

Sep 16, 2013 1:44:23 PM org.Apache.catalina.ha.tcp.SimpleTcpCluster startInternal
INFO: Cluster is about to start
Sep 16, 2013 1:44:23 PM org.Apache.catalina.tribes.transport.ReceiverBase getBind
FINE: Starting replication listener on address:10.0.0.100
Sep 16, 2013 1:44:23 PM org.Apache.catalina.tribes.transport.ReceiverBase bind
INFO: Receiver Server Socket bound to:/10.0.0.100:4001
Sep 16, 2013 1:44:23 PM org.Apache.catalina.tribes.membership.McastServiceImpl setupSocket
INFO: Setting cluster mcast soTimeout to 500
Sep 16, 2013 1:44:23 PM org.Apache.catalina.tribes.membership.McastServiceImpl waitForMembers
INFO: Sleeping for 1000 milliseconds to establish cluster membership, start level:4
Sep 16, 2013 1:44:24 PM org.Apache.catalina.tribes.membership.McastServiceImpl waitForMembers
INFO: Done sleeping, membership established, start level:4
Sep 16, 2013 1:44:24 PM org.Apache.catalina.tribes.membership.McastServiceImpl waitForMembers
INFO: Sleeping for 1000 milliseconds to establish cluster membership, start level:8
Sep 16, 2013 1:44:25 PM org.Apache.catalina.tribes.membership.McastServiceImpl waitForMembers
INFO: Done sleeping, membership established, start level:8

Wenn der zweite Server gestartet wird, protokolliert der erste Server

Sep 16, 2013 2:17:30 PM org.Apache.catalina.tribes.group.interceptors.TcpFailureDetector messageReceived
FINE: Received a failure detector packet:ClusterData[src=org.Apache.catalina.tribes.membership.MemberImpl[tcp://{10, 0, 0, 100}:4000,{10, 0, 0, 100},4000, alive=112208, securePort=-1, UDP Port=-1, id={118 6 107 -67 88 98 72 95 -73 41 4 -108 58 -5 -127 -41 }, payload={}, command={}, domain={}, ]; id={25 110 120 -2 -25 6 78 -97 -84 -34 2 -11 49 -62 -8 -56 }; sent=2013-09-16 14:17:30.139]
Sep 16, 2013 2:17:30 PM org.Apache.catalina.tribes.transport.nio.NioReplicationTask remoteEof
FINE: Channel closed on the remote end, disconnecting
Sep 16, 2013 2:17:30 PM org.Apache.catalina.tribes.membership.McastServiceImpl memberDataReceived
FINE: Mcast add member org.Apache.catalina.tribes.membership.MemberImpl[tcp://{10, 0, 0, 100}:4001,{10, 0, 0, 100},4001, alive=1010, securePort=-1, UDP Port=-1, id={82 -45 -109 -56 -110 -5 78 -10 -103 61 -40 -59 -36 -79 104 120 }, payload={}, command={}, domain={}, ]
Sep 16, 2013 2:17:30 PM org.Apache.catalina.ha.tcp.SimpleTcpCluster memberAdded
INFO: Replication member added:org.Apache.catalina.tribes.membership.MemberImpl[tcp://{10, 0, 0, 100}:4001,{10, 0, 0, 100},4001, alive=1011, securePort=-1, UDP Port=-1, id={82 -45 -109 -56 -110 -5 78 -10 -103 61 -40 -59 -36 -79 104 120 }, payload={}, command={}, domain={}, ]

und wenn einer heruntergefahren ist, protokolliert der andere

Sep 16, 2013 2:28:05 PM org.Apache.catalina.tribes.membership.McastServiceImpl memberDataReceived
FINE: Member has shutdown:org.Apache.catalina.tribes.membership.MemberImpl[tcp://{10, 0, 0, 100}:4001,{10, 0, 0, 100},4001, alive=422279, securePort=-1, UDP Port=-1, id={54 43 17 -9 13 -11 72 -63 -107 -78 -8 65 -21 -77 115 88 }, payload={}, command={66 65 66 89 45 65 76 69 88 ...(9)}, domain={}, ]
Sep 16, 2013 2:28:05 PM org.Apache.catalina.tribes.group.interceptors.TcpFailureDetector memberDisappeared
INFO: Verification complete. Member disappeared[org.Apache.catalina.tribes.membership.MemberImpl[tcp://{10, 0, 0, 100}:4001,{10, 0, 0, 100},4001, alive=422279, securePort=-1, UDP Port=-1, id={54 43 17 -9 13 -11 72 -63 -107 -78 -8 65 -21 -77 115 88 }, payload={}, command={66 65 66 89 45 65 76 69 88 ...(9)}, domain={}, ]]
Sep 16, 2013 2:28:05 PM org.Apache.catalina.ha.tcp.SimpleTcpCluster memberDisappeared
INFO: Received member disappeared:org.Apache.catalina.tribes.membership.MemberImpl[tcp://{10, 0, 0, 100}:4001,{10, 0, 0, 100},4001, alive=422279, securePort=-1, UDP Port=-1, id={54 43 17 -9 13 -11 72 -63 -107 -78 -8 65 -21 -77 115 88 }, payload={}, command={66 65 66 89 45 65 76 69 88 ...(9)}, domain={}, ]

also weiß ich, dass sie sich gegenseitig bewusst sind.

Schließlich, wenn ich die Cluster/Operations-MBean in jconsole verwende, um zu versuchen, die Eigenschaft "foo" auf "bar" festzulegen, wird die Methode "jconsole reports" erfolgreich aufgerufen, und die Serverprotokolle

Sep 16, 2013 2:30:18 PM org.Apache.catalina.ha.tcp.SimpleTcpCluster setProperty
WARNING: Dynamic setProperty(foo,value) has been disabled, please use explicit properties for the element you are trying to identify

Ich mache mir nicht zu viele Sorgen um diesen Fehler. Meistens enthalten, um zu zeigen, dass setProperty eine Protokollanweisung erstellt.

Was funktioniert nicht?

Soweit ich das beurteilen kann, werden in meiner App keine Sitzungsinformationen repliziert.

Der Tomcat-Manager listet nur Sitzungen auf, die auf dem überwachten Server gestartet wurden, und nicht den anderen im Cluster.

Ich habe den Eindruck, dass jedes Mal, wenn die App HttpSession.setAttribute aufruft, dieses Attribut auf die anderen Clusterknoten repliziert werden sollte, und ich würde davon ausgehen, dass einige Einträge davon protokolliert werden. Meine App enthält diese Zeile:

   public static void saveBillingInfo(IPageContext pageContext, BillingInfo billingInfo)
   {    
      pageContext.getSession().setAttribute("billingInfo", billingInfo);
      //etc...
   }

dabei ist BillingInfo eine serialisierbare Klasse, die nur ein Feld enthält, eine HashMap mit Informationen zu den Rechnungsinformationen.

Es werden keine Protokollanweisungen geschrieben, wenn diese oder eine andere Zeile verarbeitet wird, und ich sehe keine Hinweise darauf, dass Sitzungsinformationen tatsächlich geteilt werden.

Anregungen oder weitere Fragen sind willkommen.

18
nvioli

Wir hatten dieses identische Problem. Obwohl nirgendwo dokumentiert, löste ich das einfach, das <Manager> -Tag aus server.xml in die globale context.xml zu verschieben (um es aus der Gruppe <Server> ... <Cluster> ... zu entfernen die Gruppe <Kontext>). Sobald wir dies getan hatten, begann alles "magisch" zu arbeiten. Dies gilt nur für Tomcat 7 ... Tomcat 6 hat mit dem oben beschriebenen Setup (und wie in der Dokumentation beschrieben) einwandfrei funktioniert.

<Context>
    <Manager className="org.Apache.catalina.ha.session.DeltaManager"
             expireSessionsOnShutdown="false"
             notifyListenersOnReplication="true" />
</Context>

Nun entfernen Sie einfach das <Manager> -Tag aus Ihrer Clustergruppe in der Datei server.xml und fertig.

29
Jason

auf server.xml einfach hinzufügen:

<Cluster className="org.Apache.catalina.ha.tcp.SimpleTcpCluster"
             channelSendOptions="6"/>  

und in Ihrer context.xml:

<Manager className="org.Apache.catalina.ha.session.DeltaManager"
         expireSessionsOnShutdown="false"
         notifyListenersOnReplication="true" />

es hat für mich funktioniert, ich verwende Tomcat 7 und Tomcat 8

1
Fabian Mejia

Laut Tomcat-Dokumenten müssen Sie eine der beiden folgenden Optionen (NICHT beide) ausführen: 

  1. Geben Sie in web.xml <distributable/> an, um das Clustering zu aktivieren, und verwenden Sie den in der server.xml angegebenen Standardcode <Manager> oder ...

  2. Fügen Sie auf der Anwendungsebene in context.xml einen <Manager> hinzu

0
user6649882

Wenn Sie das Clustering für bestimmte bereitgestellte Anwendungen aktivieren möchten, können Sie das folgende Beispiel verwenden 

server.xml

  <Host name="localhost"  appBase="webapps"
        unpackWARs="true" autoDeploy="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="4000"
                  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"/>

      <Manager className="org.Apache.catalina.ha.session.DeltaManager"
       expireSessionsOnShutdown="false"
       notifyListenersOnReplication="true"/>

    <Resource auth="Container" driverClassName="Oracle.jdbc.OracleDriver" factory="com.atomikos.Tomcat.EnhancedTomcatAtomikosBeanFactory" minPoolSize="4" maxPoolSize="50" name="jdbc/myoracle/myconect" password="sdfhsfghsgfsfg" type="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean" uniqueResourceName="uniresource" url="jdbc:Oracle:thin:@10.10.10.10.:1521:abc" user="user"/>
    </Context>
0
Thanh Nguyen

Unsere Lösung bestand darin, das <distributable/>-Tag der WEB-INF/web.xml-Datei unter dem <web-app>-Element hinzuzufügen. Nicht sicher, warum dies für uns und nicht für das OP funktionierte.

Übrigens, Jasons Lösung hat auch für uns funktioniert.

0
David I