How to configure a Tomcat cluster on Ubuntu

Apache Tomcat is the most popular open-source Java web server. If your web site is expecting more traffic as your business grows, a single instance of Tomcat will probably not scale with the growing traffic. In that case, you might be thinking to run Tomcat in a "clustered" environment, where web server workload is distributed to multiple Tomcat instances.

In this article I will show you how to configure a Tomcat cluster with load balancing and session replication. Before we delve into the details about the setup, we want to clarify some of the terms we will be using in this tutorial.

Terminology

Load balancing: When HTTP requests are received by a front-end server (often called "load balancer", "proxy balancer" or "reverse proxy"), the front-end server distributes the requests to more than one "worker" web servers in the backend, which actually handle the requests. Load balancing can get rid of a single point of failure in the backend, and can achieve high availability, scalability and better resource optimization for any web service.

Session replication: Session replication is a mechanism to copy the entire state of a client session verbatim to two or more server instances in a cluster for fault tolerance and failover. Typically, stateful services that are distributed are capable of replicating client session states across different server instances in a cluster.

Cluster: A cluster is made up of two or more web server instances that work in unison to transparently serve client requests. Clients will perceive a group of server instances as a single entity service. The goal of the cluster is to provide a highly available service for clients, while utilizing all available compute resources as efficiently as possible.

Requirements

Here are the requirements for setting up a Tomcat cluster. In this tutorial, I assume there are three Ubuntu servers.

  • Server #1: Apache HTTP web server with mod_jk (for proxy balancer)
  • Server #2 and #3: Java runtime 6.x or higher and Apache Tomcat 7.x (for worker web server)

Apache web server is acting as a proxy balancer. Apache web server is the only server visible to clients, and all Tomcat instances are hidden from clients. With mod_jk extension activated, Apache web server will forward any incoming HTTP request to Tomcat worker instances in the cluster.

In the rest of the tutorial, I will describe step by step procedure for configuring a Tomcat cluster.

Step One: Install Apache Web Server with mod_jk Extension

Tomcat Connectors allows you to connect Tomcat to other open-source web servers. For Apache web server, Tomcat Connectors is available as an Apache module called mod_jk. Apache web server with mod_jk turns a Ubuntu server into a proxy balancer. To install Apache web server and mod_jk module, use the following command.

$ sudo apt-get install apache2 libapache2-mod-jk

Step Two: Install JDK and Apache Tomcat

The next step is to install Apache Tomcat on the other two Ubuntu servers which will actually handle HTTP requests as workers. Since Apache Tomcat requires JDK, you need to install it as well. Follow this guide to install JDK and Apache Tomcat on Ubuntu servers.

Step Three: Configure Apache mod_jk on Proxy Balancer

On Ubuntu, the mod_jk configuration file is located in /etc/apache2/mods-enabled/jk.conf. Update this file with the following content:

	<IfModule jk_module> 

        # We need a workers file exactly once 
        # and in the global server 
        JkWorkersFile /etc/libapache2-mod-jk/workers.properties 

        # JK error log 
        # You can (and should) use rotatelogs here 
        JkLogFile /var/log/apache2/mod_jk.log 

        # JK log level (trace,debug,info,warn,error) 
        JkLogLevel info 

        JkShmFile /var/log/apache2/jk-runtime-status 

        JkWatchdogInterval 60 

        JkMount /*  loadbalancer
        JkMount /jk-status jkstatus

        # Configure access to jk-status and jk-manager 
        # If you want to make this available in a virtual host, 
        # either move this block into the virtual host 
        # or copy it logically there by including "JkMountCopy On" 
        # in the virtual host. 
        # Add an appropriate authentication method here! 
    	<Location /jk-status> 
                # Inside Location we can omit the URL in JkMount 
       	        JkMount jk-status 
                Order deny,allow 
                Deny from all 
                Allow from 127.0.0.1 
    	</Location> 
    	<Location /jk-manager> 
      	        # Inside Location we can omit the URL in JkMount 
                JkMount jk-manager 
                Order deny,allow 
                Deny from all 
                Allow from 127.0.0.1 
    	</Location> 
	</IfModule> 

In order to make the above configuration work with multiple Tomcat instances, we have to configure every Tomcat worker instance in /etc/libapache2-mod-jk/workers.properties. We assume that the IP addresses of the two worker Ubuntu machines are 192.168.1.100 and 192.168.1.200.

Create or edit etc/libapache2-mod-jk/workers.properties with the following content:

	worker.list=loadbalancer,jkstatus

	# Configure Tomcat instance for 192.168.1.100

	worker.tomcat1.type=ajp13 
	worker.tomcat1.host=192.168.1.100 
	worker.tomcat1.port=8081
	# worker "tomcat1" uses up to 200 sockets, which will stay no more than 
	# 10 minutes in the connection pool. 
	worker.tomcat1.connection_pool_size=200
	worker.tomcat1.connection_pool_timeout=600 
	# worker "tomcat1" will ask the operating system to send a KEEP-ALIVE 
	# signal on the connection. 
	worker.tomcat1.socket_keepalive=1 

	# Configure Tomcat instance for 192.168.1.200

	worker.tomcat2.type=ajp13 
	worker.tomcat2.host=192.168.1.200 
	worker.tomcat2.port=8082
	# worker "tomcat2" uses up to 200 sockets, which will stay no more than 
	# 10 minutes in the connection pool. 
	worker.tomcat2.connection_pool_size=200
	worker.tomcat2.connection_pool_timeout=600 
	# worker "tomcat2" will ask the operating system to send a KEEP-ALIVE 
	# signal on the connection. 
	worker.tomcat2.socket_keepalive=1 

	worker.jkstatus.type=status

	worker.loadbalancer.type=lb 
	worker.loadbalancer.balance_workers=tomcat1,tomcat2

Step Four: Configure Tomcat Instances

Edit /opt/apache-tomcat-7.0.30/conf/server.xml for Tomcat instance on 192.168.1.100 with the following content:

	<Engine name="Catalina" defaultHost="192.168.1.100” jvmRoute="tomcat1">
	<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">
		<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
			<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
		</Sender>

		<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" 		port="4000" autoBind="100" selectorTimeout="5000" maxThreads="50"/>
	<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"/>
	<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
	<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>

Edit /opt/apache-tomcat-7.0.30/conf/server.xml for Tomcat instance on 192.168.1.200 with the following content:

	<Engine name="Catalina" defaultHost="192.168.1.200” jvmRoute="tomcat2">
	<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">
		<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
			<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
		</Sender>
	
		<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" 		port="4000" autoBind="100" selectorTimeout="5000" maxThreads="30"/>
	<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"/>
	<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
	<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>

Step Five: Test a Tomcat Cluster

Tomcat Connectors has a special type of worker, the so-called status worker. The status worker does not forward requests to Tomcat instances. Instead, it allows one to retrieve status and configuration information at run-time, and even to change many configuration options dynamically. You can monitor the Tomcat cluster by accessing this status worker, which can be done simply by going to http://<proxy-balancer-ip-address>/jk-status on a web browser. The following is the screenshot of the jk status management interface.

Subscribe to Xmodulo

Do you want to receive Linux FAQs, detailed tutorials and tips published at Xmodulo? Enter your email address below, and we will deliver our Linux posts straight to your email box, for free. Delivery powered by Google Feedburner.

2 thoughts on “How to configure a Tomcat cluster on Ubuntu

Leave a comment

Your email address will not be published. Required fields are marked *

Current day month ye@r *