fhanik      2003/10/14 18:57:59

  Modified:    webapps/docs index.xml project.xml
  Added:       webapps/docs cluster-howto.xml
  Log:
  added in a clustering how to, not yet completed, need to describe the configuration, 
although it is already done
  in server.xml
  
  Revision  Changes    Path
  1.11      +3 -0      jakarta-tomcat-catalina/webapps/docs/index.xml
  
  Index: index.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/webapps/docs/index.xml,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- index.xml 8 Sep 2003 10:16:02 -0000       1.10
  +++ index.xml 15 Oct 2003 01:57:59 -0000      1.11
  @@ -89,6 +89,9 @@
       Configuring MBean descriptors files for custom components.</li>
   <li><a href="default-servlet.html"><strong>Default Servlet</strong></a> -
       Configuring the default servlet and customizing directory listings.</li>
  +<li><a href="cluster-howto.html"><strong>Tomcat Clustering</strong></a> -
  +    Enable session replication in a Tomcat environment.</li>
  +
   </ol>
   
   </section>
  
  
  
  1.16      +1 -1      jakarta-tomcat-catalina/webapps/docs/project.xml
  
  Index: project.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-catalina/webapps/docs/project.xml,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- project.xml       8 Sep 2003 10:16:02 -0000       1.15
  +++ project.xml       15 Oct 2003 01:57:59 -0000      1.16
  @@ -36,7 +36,7 @@
           <item name="16) MBean Descriptor"
                 href="mbeans-descriptor-howto.html"/>
           <item name="17) Default Servlet"    href="default-servlet.html"/>
  -
  +        <item name="18) Clustering"    href="cluster-howto.html"/>
       </menu>
   
       <menu name="Reference">
  
  
  
  1.1                  jakarta-tomcat-catalina/webapps/docs/cluster-howto.xml
  
  Index: cluster-howto.xml
  ===================================================================
  <?xml version="1.0"?>
  <!DOCTYPE document [
    <!ENTITY project SYSTEM "project.xml">
  ]>
  <document url="cluster-howto.html">
  
      &project; 
  
      <properties>
          <author email="[EMAIL PROTECTED]">Filip Hanik</author>
          <title>Clustering/Session Replication HOW-TO</title>
      </properties>
  
  <body>
  
  
  <section name="Quick Start">
  
  <p>To run session replication in your Tomcat 5 container, the following steps
  should be completed:</p>
  <ul>
  <li>All your session attributes must implement <code>java.io.Serializable</code></li>
  <li>Uncomment the <code>Cluster</code> element in server.xml</li>
  <li>Uncomment the <code>Valve(ReplicationValve)</code> element in server.xml</li>
  <li>If your Tomcat instances are running on the same machine, make sure the 
<code>tcpListenPort</code>
      attribute is unique for each instance.</li>
  <li>Make sure your <code>web.xml</code> has the <code>&lt;distributable/&gt;</code> 
element</li>    
  </ul>
  <p>Then all you have to do is start Tomcat, I suggest using <a 
href="http://balance.sourceforge.net";>Balance</a>
     as a load balancer. Apache/mod_jk will also do or hardware of course</p>
  <p>Note: Remember that your session state is tracked by a cookie, so your URL must 
look the same from the out
     side otherwise, a new session will be created.</p>
  </section>
  
  
  <section name="Overview">
  
  <p>To enable session replication in Tomcat, three different paths can be followed to 
achieve the exact same thing:</p>
  <ol>
    <li>Using session persistence, and saving the session to a shared file system 
(PersistenceManager)</li>
    <li>Using session persistence, and saving the session to a shared database 
(JDBCManager)</li>
    <li>Using in-memory-replication, using the SimpleTcpCluster that ships with Tomcat 
5 (server/lib/catalina-cluster.jar)</li>
  </ol>
  
  <p>In this release of session replication, Tomcat performs an all-to-all replication 
of session state.
     
     This is an algorithm that is only efficient when the clusters are small. For 
large clusters, the next 
     release will support a primary-secondary session replication where the session 
will only be stored at one
     or maybe two backup servers.
     In order to keep the network traffic down in an all-to-all environment, you can 
split your cluster
     into smaller groups. This can be easily achieved by using different multicast 
addresses for the different groups.
     A very simple setup would look like this:
     </p>
  
  <source>
          DNS Round Robin
                 |
           Load Balancer
            /           \
        Cluster1      Cluster2
        /     \        /     \
    Tomcat1 Tomcat2  Tomcat3 Tomcat4
  </source>
  
  <p>What is important to mention here, is that session replication is only the 
beginning of clustering.
     Another popular concept used to implement clusters is farming, ie, you deploy 
your apps only to one 
     server, and the cluster will distribute the deployments across the entire cluster.
     This is all capabilities that can go into the next release.</p>
  <p>In the next section will go deeper into how session replication works and how to 
configure it.</p>
  
  </section>
  
  <section name="How it Works">
  <p>To make it easy to understand how clustering works, I'm gonna take you through a 
series of scenarios.
     In the scenario I only plan to use two tomcat instances <code>TomcatA</code> and 
<code>TomcatB</code>.
     We will cover the following sequence of events:</p>
     
  <ol>
  <li><code>TomcatA</code> starts up</li>
  <li><code>TomcatB</code> starts up</li>
  <li><code>TomcatA</code> receives a request, a session <code>S1</code> is 
created.</li>
  <li><code>TomcatA</code> crashes</li>
  <li><code>TomcatB</code> receives a request for session <code>S1</code></li>
  <li><code>TomcatA</code> starts up</li>
  <li><code>TomcatA</code> receives a request, invalidate is called on the session 
(<code>S1</code>)</li>
  <li><code>TomcatB</code> receives a request, for a new session (<code>S2</code>)</li>
  <li><code>TomcatA</code> The session <code>S2</code> expires due to inactivity.</li>
  </ol>
  
  <p>Ok, now that we have a good sequence, I will take you through exactly what 
happens in the session repliction code</p>
  
  <ol>
  <li><b><code>TomcatA</code> starts up</b>
      <p>
          Tomcat starts up using the standard start up sequence. When the Host object 
is created, a cluster object is associated with it.
          When the contexts are parsed, if the distributable element is in place in 
web.xml
          Tomcat asks the Cluster class (in this case <code>SimpleTcpCluster</code>) 
to create a manager
          for the replicated context. So with clustering enabled, distributable set in 
web.xml
          Tomcat will create a <code>SimpleTcpReplicationManager</code> for that 
context instead of a <code>StandardManager</code>.
          The cluster class will start up a membership service (multicast) and a 
replication service (tcp unicast).
          More on the architecture further down in this document.
      </p><p></p>
  </li>
  <li><b><code>TomcatB</code> starts up</b>
      <p>
          When TomcatB starts up, it follows the same sequence as TomcatA did with one 
exception.
          The cluster is started and will establish a membership (TomcatA,TomcatB).
          TomcatB will now request the session state from a server that already exists 
in the cluster, 
          in this case TomcatA. TomcatA responds to the request, and before TomcatB 
starts listening 
          for HTTP requests, the state has been transferred from TomcatA to TomcatB.
          In case TomcatA doesn't respond, TomcatB will time out after 60 seconds, and 
issue a log 
          entry. The session state gets transferred for each web application that has 
distributable in 
          its web.xml. Note: To use session replication efficiently, all your tomcat 
instances should be 
          configured the same.
      </p><p></p>
  </li>
  <li><B><code>TomcatA</code> receives a request, a session <code>S1</code> is 
created.</B>
      <p>
          The request coming in to TomcatA is treated exactly the same way as without 
session replication.
          The action happens when the request is completed, the 
<code>ReplicationValve</code> will intercept
          the request before the response is returned to the user.
          At this point it finds that the session has been modified, and it uses TCP 
to replicata the
          session to TomcatB. Once the serialized data has been handed off to the 
operating systems TCP logic,
          the request returns to the user, back through the valve pipeline.
          For each request the entire session is replicated, this allows code that 
modifies attributes
          in the session without calling setAttribute or removeAttribute to be 
replicated.
          a useDirtyFlag configuration parameter can be used to optimize the number of 
times 
          a session is replicated.    
      </p><p></p>
  
  </li>
  <li><b><code>TomcatA</code> crashes</b>
      <p>
          When TomcatA crashes, TomcatB receives a notification that TomcatA has 
dropped out 
          of the cluster. TomcatB removes TomcatA from its membership list, and 
TomcatA will no longer
          be notified of any changes that occurs in TomcatB.
          The load balancer will redirect the requests from TomcatA to TomcatB and all 
the sessions 
          are current.
      </p><p></p>
  </li>
  <li><b><code>TomcatB</code> receives a request for session <code>S1</code></b>
      <p>Nothing exciting, TomcatB will process the request as any other request.
      </p><p></p>
  </li>
  <li><b><code>TomcatA</code> starts up</b>
      <p>Upon start up, before TomcatA starts taking new request and making itself
      available to it will follow the start up sequence described above 1) 2).
      It will join the cluster, contact TomcatB for the current state of all the 
sessions.
      And once it receives the session state, it finishes loading and opens its 
HTTP/mod_jk ports.
      So no requests will make it to TomcatA until it has received the session state 
from TomcatB.
      </p><p></p>
  </li>
  <li><b><code>TomcatA</code> receives a request, invalidate is called on the session 
(<code>S1</code>)</b>
      <p>The invalidate is call is intercepted, and the session is queued with 
invalidated sessions.
          When the request is complete, instead of sending out the session that has 
changed, it sends out
          an "expire" message to TomcatB and TomcatB will invalidate the session as 
well.
      </p><p></p>
  
  </li>
  <li><b><code>TomcatB</code> receives a request, for a new session 
(<code>S2</code>)</b>
      <p>Same scenario as in step 3)
      </p><p></p>
  
  
  </li>
  <li><code>TomcatA</code> The session <code>S2</code> expires due to inactivity.
      <p>The invalidate is call is intercepted the same was as when a session is 
invalidated by the user, 
         and the session is queued with invalidated sessions.
         At this point, the invalidet session will not be replicated across until 
         another request comes through the system and checks the invalid queue.
      </p><p></p>
  </li>
  </ol>
  
  <p>Phuuuhh! :)</p>
  
  <p><b>Membership</b>
      Clustering membership is established using very simple multicast pings.
      Each Tomcat instance will periodically send out a multicast ping,
      in the ping message the instance will broad cast its IP and TCP listen port 
      for replication.
      If an instance has not received such a ping within a given timeframe, the 
      member is considered dead. Very simple, and very effective!
      Of course, you need to enable multicasting on your system.
  </p>
  
  <p><b>TCP Replication</b>
      Once a multicast ping has been received, the member is added to the cluster
      Upon the next replication request, the sending instance will use the host and
      port info and establish a TCP socket. Using this socket it sends over the 
serialized data.
      The reason I choose TCP sockets is because it has built in flow control and 
guaranteed delivery.
      So I know, when I send some data, it will make it there :)    
  </p>
  
  <p><b>Distributed locking and pages using frames</b>
      Tomcat does not keep session instances in sync across the cluster.
      The implementation of such logic would be to much overhead and cause all 
      kinds of problems. If your client accesses the same session 
      simultanously using multiple requests, then the last request
      will override the other sessions in the cluster.
  </p>
  
  </section>
  
  <section name="Cluster Architecture">
  
  <p>Component Levels:
  <source>
          Server
            |
          Service    
            | 
          Engine  
         /     \
     Cluster ReplicationValve
        |
     Manager
        |
    Session
  </source></p>
  
  
  
  </section>
  
  
  <section name="Cluster Configuration">
  <p>The cluster configuration is described in the sample server.xml file.
  What is worth to mention is that the attributes starting with mcastXXX
  are for the membership multicast ping, and the attributes starting with tcpXXX
  are for the actual TCP replication.
  </p>
  <p>
      The membership is established by all the tomcat instances are sending broadcast 
messages
      on the same multicast IP and port.
      
      The TCP listen port, is the port where the session replication is received from 
other members.
  </p>
  <p>
      The replication valve is used to find out when the request has been completed 
and initiate the 
      replication.
  </p>
  
  </section>
  
  
  <section name="FAQ">
  <p>To be completed once I receive questions about session replication:</p>
  <ol>
  <li>Q: What happens when I pull the network cord?<p></p>
  
      A: Well, the other members will remove the instance from the cluster,
         but when you insert the cable again, the Tomcat instance might have 
completely flipped out.
         This is because the OS might start going 100% CPU when a multicast message is 
sent. 
         There has not yet been a good solution for this, I will let you know when I 
have come up with one.
    </li>
  
  </ol>
  </section>
  
  </body>
  
  </document>
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to