Tomcat Clustering Steps Explained
Apache Tomcat 7 supports both horizontal and vertical clustering. Here in this article we will discuss the implementation of both types of tomcat clustering in Apache Tomcat 7. Before doing a deep drivelet’s discuss clustering architectures, where they can be implemented, and their advantages.
There are basically two types of clustering architectures implemented in a real-time IT infrastructure:
• Vertical clustering
• Horizontal clustering
Vertical clustering
Vertical clustering consists of a single hardware with multiple instances running, using shared resources from the system. This kind of setup is mainly done in development and quality systems for the developer to test the functionality of the application. Also, vertical clustering can be implemented in production in certain cases, where there is a resource crunch for the hardware. It uses the concept of a shared resource such as CPU, RAM, and so on. The following figure shows the pictorial presentation of vertical clustering:
Every architecture has its pros and cons. Let’s discuss some of the pros and cons of vertical clustering.
Advantages of vertical clustering
Following are the advantages of vertical clustering:
• No network bandwidth issue, as instances are hosted on a single machine
• Hardware is shared by different Tomcat instances
• Addition of physical hardware is not required
• Single JVM can be shared by multiple instances
Disadvantages of vertical clustering
Following are the disadvantages of vertical clustering:
• No failover in case of hardware issues
• More maintenance issues
• High-end hardware used for implementation
• High cost
Horizontal clustering
In this type of clustering method, instances are configured separately on each physical machine and connected through high speed Ethernet. It’s a very popular implementation technique in the production environment. Resources of one machine are not shared with the other machine. Also, failover can be done in the case of hardware failure. The following figure shows the horizontal clustering for different Apache Tomcat instances using separate physical hardware:
Advantages of horizontal clustering
Following are the advantages of horizontal clustering:
• Failover is possible in the case of hardware failure
• A low-end system can be used, as a single instance runs for each physical or VM instance
• Low maintenance issues
Disadvantages of horizontal clustering
Following are the disadvantages of horizontal clustering:
• Network bandwidth issues
• Network connectivity issues between machines
• Each instance requires a separate physical hardware component
Vertical clustering in Apache Tomcat 7
In the previous topics, we have discussed the different types of cluster architecture, supported by Apache Tomcat 7. It’s time to take a real-time challenge to implement clustering. Let’s start with vertical clustering.
For vertical clustering, we have to configure at least two instances of Apache Tomcat and the complete process consists of three stages. Let’s discuss and implement the steps for vertical cluster in Tomcat 7:
1. Installation of the Tomcat instance.
2. Configuration of the cluster.
3. Apache HTTP web server configuration for the vertical cluster.
Installation of the Tomcat instance
The installation of Apache Tomcat 7 can be done in three easy steps:
1. Download and unzip the software in the required directory.
2. Install the JDK and set the JAVA_HOME.
3. Copy the Apache Tomcat source code in two different directories, for example, /opt/tomcatX (where X= instance number) and verify that the files are properly copied on both instances, using the following command:
[root@localhost opt]# ls -l apache-tomcat*
The following screenshot shows the output of the previous command:
Configuration of a vertical cluster
This section is the most critical section for vertical clustering, as all the configurations are done in this section and a simple error can make the cluster non-functioning. So, be careful while carrying out the configuration. Let’s do the step-by-step configuration on each node.
Configuration of instance 1
For the first instance; node 1, we can use the default configuration, such as Connector, AJP, or shutdown port in server.xml. Let’s discuss each component where the configuration needs to be done and why it is used:
- Shutdown port: The following screenshot shows the configuration for the shutdown port for the Tomcat instance. While running multiple instances, if by any chance, you have skipped configuring the shutdown port, then the Tomcat instance will be unable to start it.
- Connector port: The following screenshot shows the Connector port configuration for Tomcat 7. This port is used to access the Tomcat instance, for example, normally we access the Tomcat instance by using http:// localhost:8080, the 8080 port is called the Connector port. While running multiple instances, if you have skipped configuring this port, then the Tomcat instance will be unable to start it and you will get the Port already in use exception.
- AJP port: The following screenshot shows the AJP port configuration for Tomcat 7. This port is used for AJP communication between the Apache HTTP server and the Tomcat instance. While running multiple instances, if you have skipped to configuring port, then the Tomcat instance will be unable to start it and you will get the Port already in use exception.
- Cluster attributes: Enable the cluster attributes for clustering in server.xml and the following screenshot shows the cluster class used for clustering:
5. Configuration test: Run the configtest.sh script from TOMCAT_HOME/bin to check the configuration. The following screenshot shows the output for the following config.sh command:
[root@localhost bin]# ./configtest.sh
6. Tomcat instance startup: Start the instance 1 configuration using the script startup.sh. The following screenshot shows the output for the following startup.sh script:
[root@localhost bin]# ./startup.sh
Check the Tomcat instance process using the following mentioned command. The following screenshot shows the output for the ps command:
[root@localhost bin]# ps -ef |grep java
Configuration of instance 2
We cannot use the default configuration on node 2. There will be port conflicts as we are running the instance with single a IP on the same physical machine. Let’s configure instance 2 step-by-step:
- Change the shutdown port for instance 2 in server.xml (increment it by 1). The following screenshot shows the configuration:
- Change the Connector and redirect the port for instance 2 in server.xml (increment it by 1). The following screenshot shows the configuration:
- Change the AJP and redirect the port for instance 2 in server.xml (increment it by 1). The following screenshot shows the configuration:
- Enable the cluster attributes for clustering in server.xml. The following screenshot shows the configuration:
5. Save server.xml.
6. Run the configtest.sh script from TOMCAT_HOME/bin to check the configuration. The following screenshot shows the output for the following startup.sh script:
[root@localhost bin]# ./configtest.sh
7. Start the configuration of instance 2 using the script startup.sh. The following screenshot shows the output for the following startup.sh script:
[root@localhost bin]# ./startup.sh
8. Check the Tomcat instance process. The following screenshot shows the output for the ps command:
[root@localhost bin]# ps -ef |grep java
9. Now, check catalina.out for both the nodes.
The logs for node 1 are similar to the following:
Oct 11, 2011 5:00:24 PM org.apache.catalina.ha.tcp. SimpleTcpCluster startInternal INFO: Cluster is about to start Oct 11, 2011 5:00:24 PM org.apache.catalina.tribes.transport.ReceiverBase bind INFO: Receiver Server Socket bound to:/127.0.0.1:4000 Oct 11, 2011 5:00:24 PM org.apache.catalina.tribes.membership.McastServiceImpl setupSocket # Instance node 1 started on port 4000 INFO: Setting cluster mcast soTimeout to 500 Oct 11, 2011 5:00:24 PM INFO: Sleeping for 1000 milliseconds to establish cluster membership, start level:8 Oct 11, 2011 5:00:26 PM org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers # waiting for other member to join the cluster org.apache.catalina.ha.session.JvmRouteBinderValve startInternal INFO: JvmRouteBinderValve started Oct 11, 2011 5:00:37 PM org.apache.coyote.AbstractProtocolHandler start INFO: Starting ProtocolHandler ["http-bio-8080"] Oct 11, 2011 5:00:37 PM org.apache.coyote.AbstractProtocolHandler start INFO: Starting ProtocolHandler ["ajp-bio-8009"] Oct 11, 2011 5:00:37 PM org.apache.catalina.startup.Catalina start INFO: Server startup in 13807 ms Oct 11, 2011 5:23:42 PM org.apache.catalina.tribes.io.BufferPool getBufferPool INFO: Created a buffer pool with max size:104857600 bytes of type:org.apache.catalina.tribes.io.BufferPool15Impl Oct 11, 2011 5:23:43 PM org.apache.catalina.ha.tcp. SimpleTcpCluster memberAdded INFO: Replication member added:org.apache.catalina.tribes.membership.MemberImpl [tcp://{127, 0, 0, 1}:4001,{127, 0, 0, 1},4001, alive=1043, securePort=-1, UDP Port=-1, id={33 91 -59 78 -34 -52 73 -9 -99 124 -53 34 69 21 -40 -82 }, payload={}, command={}, domain={}, ] #Instance 2 joined the cluster node. The logs for node 2 are similar to the following: INFO: Starting Servlet Engine: Apache Tomcat/7.0.12 Oct 11, 2011 5:23:41 PM org.apache.catalina.ha.tcp. SimpleTcpCluster startInternal INFO: Cluster is about to start Oct 11, 2011 5:23:42 PM org.apache.catalina.tribes.transport. ReceiverBase bind INFO: Receiver Server Socket bound to:/127.0.0.1:4001 Oct 11, 2011 5:23:42 PM org.apache.catalina.tribes.membership.McastServiceImpl setupSocket # Instance node 2 started on port 4001 INFO: Setting cluster mcast soTimeout to 500 Oct 11, 2011 5:23:42 PM org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers INFO: Sleeping for 1000 milliseconds to establish cluster membership, start level:4 Oct 11, 2011 5:23:43 PM org.apache.catalina.ha.tcp. SimpleTcpCluster memberAdded INFO: Replication member added:org.apache.catalina.tribes.membership.MemberImpl [tcp://{127, 0, 0, 1}:4000,{127, 0, 0, 1},4000, alive=1398024, securePort=-1, UDP Port=-1, id={28 42 60 -68 -99 126 64 -35 -118 -97 7 84 26 20 90 24 }, payload={}, command={}, domain={}, ] # Instance 1 joined the cluster node 2.
Apache web server configuration for vertical clustering
Until now, we have done the Tomcat-level configuration to configure vertical clustering in the Tomcat instance. It’s time to integrate the Apache web server to Tomcat 7. Let’s enable the integration by performing the following steps:
1. We have to create a new file called mod_jk.conf in the conf directory of APACHE_HOME/conf using the following commands:
[root@localhost apache-2.0]# cd /opt/apache-2.2.19/conf
vi mod-jk.conf
The contents of mod_jk include the following lines of code:
LoadModulejk_module modules/mod_jk.so JkWorkersFile conf/workers.properties JkLogFile logs/mod_jk.log JkLogLevel info JkMount /sample/* loadbalancer JkMount /* loadbalancer
2. Create a new file named as workers.properties in conf using the following command:
[root@localhost conf]# vi workers.properties
worker.list lists all the nodes in Tomcat through which Apache communicates using the AJP protocol. In our example, it has two nodes, as shown in the following line of code:
worker.list=tomcatnode1, tomcatnode2, loadbalancer Define the worker.list for the entire nodes in the cluster: worker.tomcatnode1.port=8009 worker.tomcatnode1.host=localhost worker.tomcatnode1.type=ajp13 worker.tomcatnode1.lbfactor=1
The previous lines of code define the tomcatnode1 properties. The highlighted code shows the AJP port and hostname of tomcatnode1, which is essential for vertical clustering:
worker.tomcatnode2.port=8010 worker.tomcatnode2.host=localhost worker.tomcatnode2.type=ajp13 worker.tomcatnode2.lbfactor=1
The previous lines of code define the tomcatnode2 properties. The highlighted code shows the AJP port and hostname of tomcatnode2. This is essential for vertical clustering.
worker.loadbalancer.type=lb worker.loadbalancer.balanced_workers=tomcatnode1, tomcatnode2 worker.loadbalancer.sticky_session=1
The previous lines of code define the load balancing properties for mod_jk.
3. The last step is to include the mod_jk.conf in the main configuration file of httpd, that is httpd.conf and reload the Apache services:
[root@localhostconf]# vi httpd.conf
Include conf/mod_jk.conf in the end of the httpd.conf.
Horizontal clustering in Apache Tomcat 7
For horizontal clustering, we have to configure at least two instances of Apache Tomcat on two different physical or virtual systems. These physical machines can be on the same physical network. It also helps in providing a high-speed bandwidth to the system There are prerequisites for configuring horizontal clustering. The following are the details:
• Time sync between the two servers
• Proper network connectivity between the two servers
• Firewall ports between the two servers (if you are connecting from a different network)
In order to configure horizontal clustering, you have to perform the following steps:
1. Installation of the Tomcat instance
2. Configuration of the cluster
3. Apache HTTP web server configuration for the horizontal cluster
Installation of the Tomcat instance
We have already discussed the installation of Tomcat in the previous section.The steps for installation will remain the same here
Configuration of the cluster
This section is the most critical section for horizontal clustering, as all the configurations are done in this section and a simple error can make the cluster not work. So, be careful before carrying out the configuration. Let’s do the step-by-step configuration on each node.
Configuration of instance 1
For the first instance, we can use the default configuration such as the Connector, AJP, or shutdown port in server.xml. Let’s discuss each component where configuration needs to be done and why it is used:
- Shutdown port: The following screenshot shows the configuration for the shutdown port for the Tomcat instance. While running multiple instances, if you have skipped configuring the port, then the Tomcat instance will be unable to initiate it.
- Connector port: The following screenshot shows the configuration of the Connector port. This port is used to access the Tomcat instance, for example, normally you access the Tomcat instance by using http:// localhost:8080. The 8080 port is called the connector port. While running multiple instances, if you have skipped configuring the port, then the Tomcat instance will be unable to start it and you will get the Port already in use exception.
- AJP port: The following screenshot shows the AJP port configuration for Tomcat. This port is used for AJP communication between the Apache HTTP and the Tomcat instance. While running multiple instances, if you have skipped configuring this port, then the Tomcat instance will be unable to start and you will get a Port already in use exception.
- Cluster attributes: Enable the cluster attributes for clustering in server.xml. The following screenshot shows the cluster class used for clustering:
In horizontal clustering every machine has a separate IP. We have to configure the broadcast address and port for the instance to connect with each other and create a cluster session. Add the following code to server. xml to enable broadcast setting and replication:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="6"> <Manager className="org.apache.catalina.ha.session. BackupManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true" mapSendOptions="6"/> <Channel className="org.apache.catalina.tribes.group. GroupChannel"> <Membership className= "org.apache.catalina.tribes.membership.McastService" address="228.0.0.4" port="54446" frequency="500" dropTime="3500"/> <Receiver className= "org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="6000" selectorTimeout="100" maxThreads="6"/> <Sender className= "org.apache.catalina.tribes.transport. ReplicationTransmitter"> <Transport className= "org.apache.catalina.tribes.transport.nio. PooledParallelSender"/> </Sender> </Channel> <Deployer className="org.apache.catalina.ha.deploy. FarmWarDeployer" tempDir="/opt/apachetomcat1/tomcat7-temp/" deployDir="/opt/apachetomcat1/tomcat7-deploy/" watchDir="/opt/apachetomcat1/tomcat7-listen/" watchEnabled="false"/> <ClusterListener className= "org.apache.catalina.ha.session.ClusterSessionListener"/> </Cluster>
The first highlighted code section shows the multicast IP. Multicast creates a communication change for these two instances. The second highlighted section shows the deployment properties for the cluster instances.
5. Configuration test: Run the configtest.sh script from TOMCAT_HOME/bin to check the configuration. The following screenshot shows the output for the following config.sh command:
[root@localhost bin]# ./configtest.sh
- Host entry: Add the instance IP in the host files (/etc/hosts). The following screenshot shows the output for /etc/hosts file:
7. Tomcat instance startup: Start the instance 1 configuration using the script startup.sh. The following screenshot shows the output for the following startup.sh script:
[root@localhost bin]# ./startup.sh
Check the Tomcat instance process using the following mentioned command. The following screenshot displays the output for the following ps command:
[root@localhost bin]# ps -ef |grep java
Configuration of instance 2
In order to start the configuration of instance 2, install Tomcat on the other machine and perform the same steps as performed on node 1.
Check catalina.out for both the nodes. The following mentioned logs show the activity performed during the startup of the Tomcat instance with the cluster instance. It also gives us complete visibility of the clustering functionality.
Oct 11, 2011 5:00:24 PM org.apache.catalina.ha.tcp.SimpleTcpCluster startInternal INFO: Cluster is about to start Oct 11, 2011 5:00:24 PM org.apache.catalina.tribes.transport. ReceiverBase bind INFO: Receiver Server Socket bound to:/192.168.1.15:4000 Oct 11, 2011 5:00:24 PM org.apache.catalina.tribes.membership.McastServiceImpl setupSocket # Instance node 1 started on port 4000 to establish cluster membership, start level:4 Oct 11, 2011 5:00:25 PM org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers INFO: Done sleeping, membership established, start level:4 Oct 11, 2011 5:00:25 PM org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers INFO: Sleeping for 1000 milliseconds to establish cluster membership, start level:8 Oct 11, 2011 5:00:26 PM org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers # waiting for other member to join the cluster INFO: Server startup in 13807 ms Oct 11, 2011 5:23:42 PM org.apache.catalina.tribes.io.BufferPool getBufferPool INFO: Created a buffer pool with max size:104857600 bytes of type:org.apache.catalina.tribes.io.BufferPool15Impl Oct 11, 2011 5:23:43 PM org.apache.catalina.ha.tcp.SimpleTcpCluster memberAdded INFO: Replication member added:org.apache.catalina.tribes.membership.MemberImpl [tcp://{192.168.1.16, 0, 0, 1}:4001,{192, 168, 1, 16},4001, alive=1043, securePort=-1, UDP Port=-1, id={33 91 -59 78 -34 -52 73 -9 -99 124 -53 34 69 21 -40 -82 }, payload={}, command={}, domain={}, ] #Instance 2 joined the cluster node The following are the logs for node 2: INFO: Starting Servlet Engine: Apache Tomcat/7.0.12 Oct 11, 2011 5:23:41 PM org.apache.catalina.ha.tcp.SimpleTcpCluster startInternal INFO: Cluster is about to start Oct 11, 2011 5:23:42 PM org.apache.catalina.tribes.transport.ReceiverBase bind INFO: Receiver Server Socket bound to:/192.198.1.16:4001 Oct 11, 2011 5:23:42 PM org.apache.catalina.tribes.membership.McastServiceImpl setupSocket # Instance node 1 started on port 4001 INFO: Setting cluster mcast soTimeout to 500 Oct 11, 2011 5:23:42 PM org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers INFO: Sleeping for 1000 milliseconds to establish cluster membership, start level:4 Oct 11, 2011 5:23:43 PM org.apache.catalina.ha.tcp.SimpleTcpCluster memberAdded INFO: Replication member added:org.apache.catalina.tribes.membership.MemberImpl [tcp://{192,168, 1, 15}:4000,{127, 0, 0, 1},4000, alive=1398024, securePort=-1, UDP Port=-1, id={28 42 60 -68 -99 126 64 -35 -118 - 97 7 84 26 20 90 24 }, payload={}, command={}, domain={}, ] # Instance 1 joined the cluster node 2.
In the previously mentioned code, four sections are highlighted. Let’s discuss each section briefly:
• The first section shows that tomcatnode1 is started and ready to receive the cluster message on port 4000.
INFO: Receiver Server Socket bound to:/192.168.1.15:4000
• The second section shows that tomcatnode2 had joined the cluster, and node 1 is getting the notification.
added:org.apache.catalina.tribes.membership.MemberImpl[tcp:// {192.168.1.16, 0, 0, 1}:4001,{192, 168, 1, 16},4001, alive=1043
• The third section shows that tomcatnode2 is started and ready to receive the cluster message on port 4000.
INFO: Receiver Server Socket bound to:/192.198.1.16:4001
• The fourth section shows that tomcatnode1 had joined the cluster, and node 2 is getting the notification.
added:org.apache.catalina.tribes.membership.MemberImpl[tcp:// {192,168, 1, 15}:4000,{127, 0, 0, 1},4000, alive=1398024
Apache web server configuration for horizontal clustering
We have done the Tomcat level configuration to configure horizontal clustering on the Tomcat instance. It’s time to integrate the Apache web server to Tomcat 7. Let’s enable the integration by performing the following steps:
1. We have to create a new file called mod_jk.conf in the conf directory of APACHE_HOME/conf using the following commands:
[root@localhost apache-2.0]# cd /opt/apache-2.2.19/conf
vi mod-jk.conf
The following mentioned code defines the configuration parameters for mod_ jk.conf:
LoadModule jk_module modules/mod_jk.so JkWorkersFile conf/workers.properties JkLogFile logs/mod_jk.log JkLogLevel info JkMount /sample/* loadbalancer JkMount /* loadbalancer
2. Create a new file named workers.properties in the conf directory using the following command:
[root@localhost conf]# vi workers.properties
worker.list=tomcatnode1, tomcatnode2, loadbalancer Define the worker.list for the entire nodes in the cluster: worker.tomcatnode1.port=8009 worker.tomcatnode1.host=192.168.1.15 worker.tomcatnode1.type=ajp13 worker.tomcatnode1.lbfactor=1
The previous lines of code define the tomcatnode1 properties. The highlighted code shows the IP address of tomcatnode1. This is essential for horizontal clustering.
worker.tomcatnode2.port=8009 worker.tomcatnode2.host=192.168.1.16 worker.tomcatnode2.type=ajp13 worker.tomcatnode2.lbfactor=1
The previous lines of code define the tomcatnode2 properties. The highlighted code shows the IP address of tomcatnode2. This is essential for horizontal clustering.
worker.loadbalancer.type=lb worker.loadbalancer.balanced_workers=tomcatnode1, tomcatnode2 worker.loadbalancer.sticky_session=1
The previous lines of code define the load balancing properties for mod_jk.
Note: The only difference in the Apache configuration for workers.properties for horizontal and vertical clustering is vertical hosting. (worker.tomcatnode2.host is configured as localhost, whereas in horizontal clustering worker.tomcatnode2.host is configured with the IP address of a different machine.)
3. The last step is to include the mod_jk.conf in the main configuration file of httpd, that is httpd.conf and reload the Apache services using the following command:
[root@localhost conf]# vi httpd.conf
Include conf/mod_jk.conf in the end of httpd.conf.
Testing of the clustered instance
To perform cluster testing, we are going to take you through a sequence of events. In the following event, we only plan to use two Tomcat instances—tomcatnode1 and tomcatnode2. We will cover the following sequence of events:
1. Start tomcatnode1.
2. Start tomcatnode2 (wait for node 1 to start completely).
3. Node 1 crashes.
4. Node 2 takes over the user session of node 1 to node 2.
5. Start node 1 (wait for node 1 to start completely).
6. Node 2 and node 1 are in running state.
Now we have a good scenario with us, we will walk through how the entire process works:
- Start instance 1: tomcatnode1 starts up using the standard startup sequence. When the host object is created, a cluster object is associated with it. Tomcat asks the cluster class (in this case SimpleTcpCluster) to create a manager for the cluster and the cluster class will start up a membership service. The membership service is a mechanism in the cluster instance through the cluster domain, which adds the member node in the cluster. In simple terms, it is a service through which members are able to join the cluster.
- Start instance 2: When Tomcat instance 2 starts up, it follows the same sequence as tomcatnode2 with one difference. The cluster is started and will establish a connection (tomcatnode1, tomcatnode2). tomcatnode2 will now send a request to the server that already exists in the cluster, which is now tomcatinstance2.
In case the Tomcat instance does not respond within an interval of 60 seconds, then Tomcat instance 2 will update the cluster, and generate the entry in the logs. - Node 1 crashes: Once the Tomcat instance crashes, the cluster manager will send a notification to all the members, in our case it’s tomcatnode2. The entire session of node 1 will be replicated to node 2, but the user will not see any issues while browsing the website.
- Node 2 will take over the user session of node 1 to node 2: tomcatnode2 will process the request as with any other request. User requests are served with node 2.
- Start instance 1: Upon start up, tomcatnode1 first joins the cluster, and then contacts tomcatnode2 for the current state of all the users in the session. It starts serving the user requests and shares the load for node 2.
- Node 2 and node 1 are in running state: Now both the instances are in running state. Node 2 will continue to serve the user requests and once the request is served, it will terminate the user session.
- If the previous mentioned test is working, it means clustering is working fine.
Monitoring of Tomcat clustering
Once the cluster is up and working, the next stage is to set up the monitoring of the clustering. This can be done in the following ways:
• Various monitoring tools
• Scripts
• Manual
Following are the steps to manually monitor the clusters:
1. Check the Tomcat process using the following command:
root@localhost bin]# ps -ef |grep java
2. Check the logs to verify the connectivity of the cluster.
3. Verify the URL for both cluster members.
In case of any ©Copyright or missing credits issue please check CopyRights page for faster resolutions.
Here is Nice Write up..
Here are the full details to configure Tomcat cluster + mod jk + session id repilcation + Sticky Session
http://ganeshghube.blogspot.com/2015/10/configure-tomcat-cluster-load-balancing.html
This is a good guide, but the formatting is pretty bad (hard to traverse) and the screencaps are totally illegible…