What is clustering ?

The success of your web-application lies in the way that your application server can handle the load, availability and scalability. Clustering is a solution for handling these necessities. I am trying to explain the easiest way of configuring your servers for load-balancing and clustering. I am going to use Apache 2.2 as the load-balancer and Tomcat 5.5.X as the application server. So here we start:

Configuring Apache as load-balancer

For load balancing we need to configure mod_jk module for Apache server. mod_jk is available in source distribution for all Windows and most Unix platforms. You will have to download, build and configure Apache for mod_jk support.

The key here is the ‘worker.properties’ file that we use to configure the load-balancing nodes. A node is a unit (-a machine-) that can handle the request that is served by load-balancer. These nodes communicate with each-other via ajp13 port (thats the port we are using here)

A typical worker.properties file will look like this:

# Define list of workers that will be used
# for mapping requests
worker.list=loadbalancer,status

# Define Node1
# modify the host as your host IP or DNS name.
worker.node1.port=8009
worker.node1.host=xmws05
worker.node1.type=ajp13
worker.node1.lbfactor=1
worker.node1.cachesize=10


# Define Node2
# modify the host as your host IP or DNS name.
worker.node2.port=8009
worker.node2.host=xmws101
worker.node2.type=ajp13
worker.node2.lbfactor=1
worker.node2.cachesize=10

# Load-balancing behaviour
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=node1,node2
worker.loadbalancer.sticky_session=1
#worker.list=loadbalancer


# Status worker for managing load balancer
worker.status.type=status

Re-start the Apache server. Its ready for load-balancing !!

Cluster configuration of Tomcat Server

The Jini programming model

The Jini programming model [image source: Sun Microsystems]

We will dive directly into the configuration of Apache Tomcat Server for clustering.

server.xml

A typical ’server .xml’ configuration file for tomcat clustering will look like this: (Only the sections that need modification is shown)

.....

<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector enableLookups="false" port="8009" protocol="AJP/1.3" redirectPort="8443" />

.....

<!-- Define the top level container in our container hierarchy -->
<Engine defaultHost="localhost" name="Catalina" jvmRoute="node1">

.....

<Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"

doClusterLog="true" clusterLogName="clusterlog"
manager.className="org.apache.catalina.cluster.session.DeltaManager"
manager.expireSessionsOnShutdown="false"
manager.notifyListenersOnReplication="false"
manager.notifySessionListenersOnReplication="false"
manager.sendAllSessions="false" manager.sendAllSessionsSize="500"
manager.sendAllSessionsWaitTime="20">

<Membership className="org.apache.catalina.cluster.mcast.McastService"

mcastAddr="228.0.0.4" mcastBindAddress="192.168.0.101"
mcastClusterDomain="d10" mcastPort="45564" mcastFrequency="200"
mcastDropTime="30000" />

<Receiver className="org.apache.catalina.cluster.tcp.ReplicationListener"

tcpListenAddress="192.168.0.101" tcpListenPort="9015"
tcpSelectorTimeout="100" tcpThreadCount="6" />

<Sender className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"

replicationMode="fastasyncqueue" recoverTimeout="500"
recoverCounter="6" doTransmitterProcessingStats="true"
doProcessingStats="true" doWaitAckStats="true"
queueTimeWait="true" queueDoStats="true" queueCheckLock="true"
ackTimeout="15000" waitForAck="true" keepAliveTimeout="80000"
keepAliveMaxRequestCount="-1" />

<Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"

filter=".*\.gif;.*\.js;.*\.css;.*\.png;.*\.jpeg;.*\.jpg;.*\.html;.*\.txt;"
primaryIndicator="true" />

<Valve className="org.apache.catalina.cluster.session.JvmRouteBinderValve" enabled="true" />

<ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener" />
<ClusterListener className="org.apache.catalina.cluster.session.JvmRouteSessionIDBinderListener" />


<Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"

tempDir="${catalina.base}/war-temp"
deployDir="${catalina.base}/war-deploy/"
watchDir="${catalina.base}/war-listen/" watchEnabled="true" />

</Cluster>

....

That’s it !! you are done with clustering. One thing you need to make sure of is that no two instances of the server running on the same machine have same ajp13, non-SSL and SSL ports.

Making your application distributable.

In-order to have your application to run in clustered environment you need to make sure that you have put “<distributable/>” tag in your application’s deployment descriptor. Also you need to have all the classess that are put in session needs to implement java.io.Serializable interface. This is because, in clustering environment Tomcat Server timely replicates the session data across all the members that are in the cluster. So for the sake of this replication, we need to have all the session data – Serializable.

You are almost done with clustering and load-balancing. A further more configuration of Apache Server’s httpd.conf is required to plunge into clustering world. You have to add ‘AllowEncodedSlashes On’ to the Global space of the’httpd.conf’ file. This is because the uris’ that mod_jk delivers to the application server may get double decoded so that the characters like ‘/’, ‘%’ etc. will get double decoded thereby creating invalid uris.

To add more, you can refer the following links for an in-depth idea of clustering.

Wish You a Happy Clustering !!!