Last updated on September 14, 2020 by Dan Nanni
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.
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.
Here are the requirements for setting up a Tomcat cluster. In this tutorial, I assume there are three Ubuntu servers.
#1
: Apache HTTP web server with mod_jk
(for proxy balancer)
#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.
mod_jk
ExtensionTomcat 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
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.
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
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>
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.
This website is made possible by minimal ads and your gracious donation via PayPal or credit card
Please note that this article is published by Xmodulo.com under a Creative Commons Attribution-ShareAlike 3.0 Unported License. If you would like to use the whole or any part of this article, you need to cite this web page at Xmodulo.com as the original source.
Xmodulo © 2021 ‒ About ‒ Write for Us ‒ Feed ‒ Powered by DigitalOcean