Clustering Apache Tomcat. Session replication and high availability.




Apache Tomcat Clustering and load balancing

Why we need Tomcat clustering with session replication? The main idea behind clustering is making application stable, HA - high availability and load distribution. There are many techniques for load balancing with different algorithms, like round robin, request, session, busiest server and failover. The idea behind is to send incoming requests to different web servers, based on selected load balancing algorithm. Since requests coming from same session can be handled by different web servers, session create on tamcatA, will not be available on tomcatA, and in this case user experience will be impacted. To resolve this situation it is required to configure apache tomcat for session replication. In such way, all sessions created on one web server will be replicated to another.

Here is conceptual solution:

apache tomcat clustering configuration

Configure apache tomcat for session replication:

1) Uncomment Cluster element in server.xml on both tomcat web servers
2) Change tcpListenPort for each web server (must be different)
3) Change Engine element by adding jvmRoute="tomcatA" for first tomcat web server and jvmRoute="tomcatB" for second tomcat webserver.
Here are server.xml configuration files:
Server.xml for tomcat A:
					
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcatA">
...
<Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
managerClassName="org.apache.catalina.cluster.session.DeltaManager"
expireSessionsOnShutdown="false"
useDirtyFlag="true"
notifyListenersOnReplication="true">
<Membership
className="org.apache.catalina.cluster.mcast.McastService"
mcastAddr="228.0.0.4"
mcastPort="45564"
mcastFrequency="500"
mcastDropTime="3000"/>
<Receiver
className="org.apache.catalina.cluster.tcp.ReplicationListener"
tcpListenAddress="auto"
tcpListenPort="4006"
tcpSelectorTimeout="100"
tcpThreadCount="6"/>
<Sender
className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
replicationMode="pooled"
ackTimeout="15000"
waitForAck="true"/>
<Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
<Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>
<ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/>
</Cluster>
....

Server.xml for tomcat B:
					
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcatB">
...
<Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
managerClassName="org.apache.catalina.cluster.session.DeltaManager"
expireSessionsOnShutdown="false"
useDirtyFlag="true"
notifyListenersOnReplication="true">
<Membership
className="org.apache.catalina.cluster.mcast.McastService"
mcastAddr="228.0.0.4"
mcastPort="45564"
mcastFrequency="500"
mcastDropTime="3000"/>
<Receiver
className="org.apache.catalina.cluster.tcp.ReplicationListener"
tcpListenAddress="auto"
tcpListenPort="4007"
tcpSelectorTimeout="100"
tcpThreadCount="6"/>
<Sender
className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
replicationMode="pooled"
ackTimeout="15000"
waitForAck="true"/>
<Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
<Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>
<ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/>
</Cluster>
....

Also we should add <distributable/> between <web-app> into $TOMCAT_HOME/webapps/ROOT/WEB-INF/web.xml:
					
<web-app>
<distributable/>
<context-param>
<company_id <param-value>liferay.com </context-param>
...
</web-app>

Adding load balancer

Download Apache webservers and mod_jk.
Install apache web server. Copy mod_jk.so into "C:\Program Files\Apache Software Foundation\Apache2.2\modules".
Update httpd.conf as shown below:
					
LoadModule jk_module modules/mod_jk.so
<IfModule jk_module>
JkWorkersFile "C:/Program Files/Apache Software Foundation/Apache2.2/conf/workers.properties"
JkLogFile "C:/Program Files/Apache Software Foundation/Apache2.2/logs/mod_jk.log"
JkLogLevel info
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
JkMount /* loadbalancer
</IfModule>

Create workers.properties file under "C:/Program Files/Apache Software Foundation/Apache2.2/conf/":
					
worker.list=loadbalancer
worker.tomcata.type=ajp13
worker.tomcata.host=localhost
worker.tomcata.port=8009
worker.tomcata.lbfactor=1
worker.tomcata.cachesize=10
worker.tomcata.cache_timeout=600
worker.tomcata.socket_keepalive=1
worker.tomcata.socket_timeout=300
worker.tomcatb.type=ajp13
worker.tomcatb.host=localhost
worker.tomcatb.port=8109
worker.tomcatb.lbfactor=1
worker.tomcatb.cachesize=10
worker.tomcatb.cache_timeout=600
worker.tomcatb.socket_keepalive=1
worker.tomcatb.socket_timeout=300
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=tomcata,tomcatb
worker.loadbalancer.method=R

Change server.xml as follows:

Tomcat A:

<Connector port="8009" enableLookups="false" redirectPort="443" protocol="AJP/1.3" />

Tomcat B:

<Connector port="8109" enableLookups="false" redirectPort="443" protocol="AJP/1.3" />

Now, after all is set, your environment is clustered with session replication. Please note you can configure your web servers to run in failover mode. Meaning, only one web server is working, while second is idle. If some reason the working web server goes down, the backup server will take over.
You can configure your web servers to run in failover mode by changing workers.properties:
					
worker.list=loadbalancer
worker.tomcata.type=ajp13
worker.tomcata.host=localhost
worker.tomcata.port=8009
worker.tomcata.lbfactor=1
worker.tomcata.cachesize=10
worker.tomcata.cache_timeout=600
worker.tomcata.socket_keepalive=1
worker.tomcata.socket_timeout=300
worker.tomcata.redirect=tomcatb
worker.tomcatb.type=ajp13
worker.tomcatb.host=localhost
worker.tomcatb.port=8109
worker.tomcatb.lbfactor=1
worker.tomcatb.cachesize=10
worker.tomcatb.cache_timeout=600
worker.tomcatb.socket_keepalive=1
worker.tomcatb.socket_timeout=300
worker.tomcatb.activation=disabled
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=tomcata,tomcatb




Please leave your comments