Load Balancing With Tomcat
Load Balancing With Tomcat
Load Balancing With Tomcat
optimisation
To cut long story short, the idea of high-availability clusters aims at creating failure resistant,
reliable, and ultra fast blistering systems.
HA clusters most commonly use the following techniques (or should I say "buzzwords"?):
• clustering
• load balancing
• failover
• session replication
There are lots of documentation, forums, blog posts about it, but they are full of errors
(including Apache's official mod_proxy documentation).
Here I show you how to cluster, load balance, failover, and replicate session using Apache
HTTP Sever 2.2.11 and Apache Tomcat 6.0.20.
1
The infrastructure
:
I have three machine:
public is a front-end Apache HTTP which balances traffic and distributes the requests to two
backend Tomcats.
Optimisation
I did some additional things to make my HA cluster even more swift, my tips are:
• use AJP communication protocol - AJP is a binary protocol and is far more efficient
than verbose text-based HTTP protocol
• use APR based Apache Tomcat Native library - it allows optimal performance in
production environment, when enabled, the AJP connector will use a socket poller for
keepalive, increasing scalability of the server, also this will reduce significantly the
amount of processing threads needed by Tomcat
• unload all unnecessary modules on Apache HTTP Server - simply don't waste your
CPU and memory for things that wan't be used at all
• optimise JVM parameters - last year I wrote an article about JVM performance
tuning for Java EE, you can read it here: Tuning JVM for Java EE development
• http://httpd.apache.org/docs/2.2/mod/mod_proxy.html
• http://httpd.apache.org/docs/2.2/mod/mod_proxy_ajp.html
• http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html
I opened conf/httpd.conf file and uncommented these modules:
view source
print?
1.LoadModule proxy_module modules/mod_proxy.so
2.LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
3.LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
Then, at the end of includes list, I added:
view source
print?
1.# Proxy
2.Include conf/extra/httpd-proxy.conf
Finally, I created conf/extra/httpd-proxy.conf file and wrote:
view source
print?
01.<Proxy balancer://wwwcluster>
02.BalancerMember ajp://172.16.253.88:8009 route=www1
03.BalancerMember ajp://172.16.253.7:8009 route=www2
04.</Proxy>
05.
06.ProxyPass /test-app balancer://wwwcluster/test-app
stickysession=JSESSIONID
07.
08.<Location /balancer-manager>
09.SetHandler balancer-manager
10.Order Deny,Allow
11.Deny from all
12.Allow from localhost
13.</Location>
Apache Tomcat clustering and routing
On both Tomcats, I opened conf/server.xml and, as a first child of default <Host />
element, I copied and pasted the following <Cluster /> definition:
view source
print?
01.<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
02.channelSendOptions="8">
03.<Manager className="org.apache.catalina.ha.session.DeltaManager"
04.expireSessionsOnShutdown="false" notifyListenersOnReplication="true" />
05.<Channel className="org.apache.catalina.tribes.group.GroupChannel">
06.<Membership
className="org.apache.catalina.tribes.membership.McastService"
07.address="228.0.0.4" port="45564" frequency="500" dropTime="3000" />
08.<Receiver
className="org.apache.catalina.tribes.transport.nio.NioReceiver"
09.address="auto" port="4000" autoBind="100" selectorTimeout="5000"
10.maxThreads="6" />
11.<Sender
className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
12.<Transport
13.className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"
/>
14.</Sender>
15.<Interceptor
16.className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetect
or" />
17.<Interceptor
18.className="org.apache.catalina.tribes.group.interceptors.MessageDispatch1
5Interceptor" />
19.<!-- prints stats on message traffic -->
20.<Interceptor
21.className="org.apache.catalina.tribes.group.interceptors.ThroughputInterc
eptor" />
22.</Channel>
23.<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
24.filter="" />
25.<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve" />
26.<ClusterListener
27.className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener
" />
28.<ClusterListener
29.className="org.apache.catalina.ha.session.ClusterSessionListener" />
30.</Cluster>
Also, I added jvmRoute attributes to <Engine /> element, on both Tomcats respectively:
view source
print?
1.<Engine name="Catalina" defaultHost="localhost" jvmRoute="www1">
2.<Engine name="Catalina" defaultHost="localhost" jvmRoute="www2">
Load balancing and sticky sessions
OK, now as I showed you how I created my test application and how I configured my servers,
you can follow my steps to see how clustering, load balancing, failover and session replication
work.
Go to:
view source
print?
1.http://localhost/test-app
There will be an error:
1.503 Service Temporarily Unavailable
2.
3.The server is temporarily unable to service your request due to
maintenance downtime or capacity problems. Please try again later.
When you'll access this URL:
view source
print?
1.http://localhost/balancer-manager
you will see that both Tomcats have status set to Err. They are simply stopped, thus cannot be
connected to, thus the Err status.
One thing was weird, routes were not set as defined in conf/extra/httpd-proxy.conf, they
were blank:
Thankfully, they can be changed from within balancer-manger, just click on a cluster
member and set proper routes: www1 and www2, just as in proxy config file.
Session ID is the same as previously, but this time www2 is appended at the end. Counter's
value was replicated.
When you start 172.16.253.88 Tomcat, in 172.16.253.7 Tomcat's console you will see:
1.2009-01-02 10:40:40 org.apache.catalina.ha.tcp.SimpleTcpCluster
memberAdded
2.INFO: Replication member
added:org.apache.catalina.tribes.membership.MemberImpl[tcp://{-84, 16, -3,
88}:4000,{-84, 16, -3, 88},4000, alive=1016,id={-2
3.3 -9 50 91 -8 -56 75 11 -86 -107 -46 -16 75 99 -21 8 }, payload={},
command={}, domain={}, ]
If you open another browser, load balancer probably will redirect you to just recovered
172.16.253.88 Tomcat.
Summary
I know it looks simple (and it really is simple!), but there is so much rubbish, misleading, out-
dated information out there to dig through... It always takes some time to find something
useful.
If you have any questions, and I think you will, just shoot, but don't kill :)
Cheers,
Łukasz