{"id":1238,"date":"2012-08-30T16:14:55","date_gmt":"2012-08-30T08:14:55","guid":{"rendered":"http:\/\/rmohan.com\/?p=1238"},"modified":"2012-08-30T16:16:00","modified_gmt":"2012-08-30T08:16:00","slug":"tomcat-clustering-and-failover","status":"publish","type":"post","link":"https:\/\/mohan.sg\/?p=1238","title":{"rendered":"Tomcat clustering and failover"},"content":{"rendered":"<h2>\u00a0<\/h2>\n<p>In this post I will describe how to implement a functional Tomcat cluster with load balancing and failover<\/p>\n<p>I did a great deal of research trying to get this environment working. There are a number of good tutorials for simple Tomcat clustering and load balancing. I was unable to find an example that was complete which provided a load balanced solution with failover.<\/p>\n<p>Example 1 shows load balancing with a single server.<\/p>\n<p><a href=\"http:\/\/rmohan.com\/wp-content\/uploads\/2012\/08\/TomcatLoadBalancer1-300x190.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1239\" title=\"TomcatLoadBalancer1-300x190\" src=\"http:\/\/rmohan.com\/wp-content\/uploads\/2012\/08\/TomcatLoadBalancer1-300x190.png\" alt=\"\" width=\"300\" height=\"190\" srcset=\"https:\/\/mohan.sg\/wp-content\/uploads\/2012\/08\/TomcatLoadBalancer1-300x190.png 300w, https:\/\/mohan.sg\/wp-content\/uploads\/2012\/08\/TomcatLoadBalancer1-300x190-150x95.png 150w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Example 2 shows load balancing with a multiple Tomcat servers.<\/p>\n<p><a href=\"http:\/\/rmohan.com\/wp-content\/uploads\/2012\/08\/TomcatLoadbalancer21-300x215.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1240\" title=\"TomcatLoadbalancer21-300x215\" src=\"http:\/\/rmohan.com\/wp-content\/uploads\/2012\/08\/TomcatLoadbalancer21-300x215.png\" alt=\"\" width=\"300\" height=\"215\" srcset=\"https:\/\/mohan.sg\/wp-content\/uploads\/2012\/08\/TomcatLoadbalancer21-300x215.png 300w, https:\/\/mohan.sg\/wp-content\/uploads\/2012\/08\/TomcatLoadbalancer21-300x215-150x107.png 150w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Example 3 shows load balancing with failover which is described in this post.<\/p>\n<p><a href=\"http:\/\/rmohan.com\/wp-content\/uploads\/2012\/08\/TomcatFailover-241x300.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1241\" title=\"TomcatFailover-241x300\" src=\"http:\/\/rmohan.com\/wp-content\/uploads\/2012\/08\/TomcatFailover-241x300.png\" alt=\"\" width=\"241\" height=\"300\" srcset=\"https:\/\/mohan.sg\/wp-content\/uploads\/2012\/08\/TomcatFailover-241x300.png 241w, https:\/\/mohan.sg\/wp-content\/uploads\/2012\/08\/TomcatFailover-241x300-120x150.png 120w\" sizes=\"(max-width: 241px) 100vw, 241px\" \/><\/a><\/p>\n<p>The first step in setting up a cluster like we have above is to insure that multicast works in your environment. In order to check for multicast support on Linux first check to see if your kernel was compiled with multicast support by trying the following:<\/p>\n<p><code>cat proc\/net\/dev_mcast<\/code><\/p>\n<p>If the file doesn\u2019t exist a kernel recompile is in order, the instructions for this are outside the scope of this post. Assuming we have kernel multicast support we must check that it is working. This can be done with a simple java utility contained in the zipfile\u00a0<a href=\"http:\/\/www.mhelmore.com\/files\/multicasttest.zip\">multicasttest.zip<\/a>. There are 2 classes in the zipfile,\u00a0TestServer and\u00a0TestClient first start the test client on all nodes in the cluster, then run TestServer on one of the nodes with the number of messages to send as a count. This will send a message every 3 seconds until the message count is reached. All of the clients should report each message in the form \u201cReceived: Message 1 of 10? and the server will display \u201cSending message 1?. If each of the clients report the messages your clustering should work.<\/p>\n<p>Next configure your Tomcat servers for clustering and failover. Samples of the configuration file shown below are contained in the zipfile <a href=\"http:\/\/www.mhelmore.com\/files\/SampleConfig.zip\">SampleConfig.zip<\/a>.<\/p>\n<p>Add the following block in your [TOMCAT]\/conf\/server.xml:<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&lt;!\u2013 mod_jk ajp protocol connector \u2013&gt;<\/p>\n<p>&lt;Connector port=\u201d8009? protocol=\u201dAJP\/1.3? redirectPort=\u201d8443? server=\u201dApache\u201d \/&gt;<\/p>\n<p>&nbsp;<\/p>\n<pre><code>&lt;!-- Engine with clustering support set jvmRoute to \"jvm\"+id unique to tomcat instance --&gt;<\/code><\/pre>\n<p>&nbsp;<\/p>\n<pre><code>&lt;Engine name=\"Catalina\" defaultHost=\"localhost\" jvmRoute=\"jvm2\"&gt;<\/code><\/pre>\n<p>&nbsp;<\/p>\n<pre><code>&lt;Cluster className=\"org.apache.catalina.ha.tcp.SimpleTcpCluster\" channelSendOptions=\"8\"&gt;<\/code><\/pre>\n<p>&nbsp;<\/p>\n<pre><code>&lt;Manager className=\"org.apache.catalina.ha.session.DeltaManager\" expireSessionsOnShutdown=\"false\" notifyListenersOnReplication=\"true\"\/&gt;<\/code><\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<pre>&lt;Channel className=\"org.apache.catalina.tribes.group.GroupChannel\"&gt;<\/pre>\n<pre>&lt;!--Membership address and port should be set to the proper<\/pre>\n<pre>value for the environment --&gt;<\/pre>\n<pre>&lt;Membership className=\"org.apache.catalina.tribes.membership.McastService\"<\/pre>\n<pre>address=\"228.0.0.4\" port=\"45564\" frequency=\"500\" dropTime=\"3000\"\/&gt;<\/pre>\n<pre>&lt;Sender className=\"org.apache.catalina.tribes.transport.ReplicationTransmitter\"&gt;<\/pre>\n<pre>&lt;Transport className=\"org.apache.catalina.tribes.transport.nio.PooledParallelSender\"\/&gt;<\/pre>\n<pre>&lt;\/Sender&gt;<\/pre>\n<pre>&lt;Receiver className=\"org.apache.catalina.tribes.transport.nio.NioReceiver\"\r\naddress=\"auto\" port=\"4000\" autoBind=\"100\" selectorTimeout=\"5000\" maxThreads=\"6\"\/&gt;<\/pre>\n<pre>&lt;Interceptor className=\"org.apache.catalina.tribes.group.interceptors.TcpFailureDetector\"\/&gt;<\/pre>\n<pre>&lt;Interceptor className=\"org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor\"\/&gt;<\/pre>\n<pre>&lt;\/Channel&gt;\r\n&lt;Valve className=\"org.apache.catalina.ha.tcp.ReplicationValve\" filter=\"\"\/&gt;\r\n&lt;Valve className=\"org.apache.catalina.ha.session.JvmRouteBinderValve\"\/&gt;\r\n&lt;ClusterListener className=\"org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener\"\/&gt;\r\n&lt;ClusterListener className=\"org.apache.catalina.ha.session.ClusterSessionListener\"\/&gt;\r\n&lt;\/Cluster&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>Create an [APACHE]\/conf\/httpd.conf:<br \/> Include conf\/mod_jk.conf<\/p>\n<p>Save the following to [APACHE]\/conf\/mod_jk.conf and enter the following:<\/p>\n<p>LoadModule jk_module modules\/mod_jk.so<\/p>\n<p># Specify path to worker configuration file<br \/> JkWorkersFile conf\/workers.properties<\/p>\n<p># Configure logging and memory<br \/> JkShmFile logs\/mod_jk.shm<br \/> JkLogFile logs\/mod_jk.log<br \/> JkLogLevel debug<\/p>\n<p># Configure monitoring<br \/> JkMount \/jkmanager\/* jkstatus<\/p>\n<p>&lt;Location \/jkmanager&gt;<br \/> Order deny,allow<br \/> Deny from all<br \/> Allow from localhost<br \/> &lt;\/Location&gt;<\/p>\n<p># Configure applications<br \/> JkMount \/myApp\/* loadbalancer<br \/> JkMount \/myOtherApp\/* loadbalancer<\/p>\n<p>&nbsp;<\/p>\n<p>Create an [APACHE]\/conf\/workers.properties and enter the following:<\/p>\n<p># Define worker names<br \/> worker.list=worker1, worker2, jkstatus, loadbalancer<\/p>\n<p># Create virtual workers<br \/> worker.jkstatus.type=status<br \/> worker.loadbalancer.type=lb<\/p>\n<p># Declare Tomcat server worker 1 on the localhost<br \/> worker.worker1.type=ajp13<br \/> worker.worker1.distance=1<br \/> worker.worker1.port=8009<br \/> worker.worker1.host=localhost<\/p>\n<p># Declare Tomcat server worker 2 on the remote host<br \/> # setting the host value to the remote ip address<br \/> worker.worker2.type=ajp13<br \/> worker.worker2.distance=10<br \/> worker.worker2.port=8009<br \/> worker.worker2.host=XXX.XXX.XXX.XXX #IP address of remote server<\/p>\n<p># Associate real workers with virtual LoadBalancer worker<br \/> worker.loadbalancer.balanced_workers=worker1, worker2<br \/> worker.loadbalancer.sticky_session=1<\/p>\n<p>You should now be able to start your Apache and Tomcat instances and have clustering and failover.<\/p>\n<p>For this example Tomcat 6.0.29 was used with Apache 2.2 and mod_jk 1.2.31.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>Clustering allows us to run an application on several parallel servers (i.e. cluster nodes). The load is distributed across different servers, and even if any of the servers fails the application is still accessible via other cluster nodes. Clustering is crucial for scalable enterprise applications, as you can improve performance by simply adding more nodes to the cluster.<\/p>\n<p>This document provides step by step instructions for configuring Apache server which handles\u00a0\u00a0 <br \/>request for static contents and delegates request for dynamic pages (i.e. JSP or Servlet) to two\u00a0 instances of Tomcat server using JK Connectors.<\/p>\n<ul>\n<li>Installation of Apache Server<\/li>\n<li>Setting up tomcat instances\u00a0<\/li>\n<li>Configuration of Clustering for tomcat instances with JK Connectors\u00a0<\/li>\n<\/ul>\n<h5><strong>Installation of Apache Server <\/strong><\/h5>\n<p>Download windows installer for Apache Server 2.0.63 from <a href=\"http:\/\/httpd.apache.org\/download.cgi\">http:\/\/httpd.apache.org\/download.cgi<\/a> and install the same into C:\\Program Files\\Apache\u00a0 <br \/>Software Foundation.<\/p>\n<h5><strong>Setting up tomcat instances<\/strong><\/h5>\n<p>Download apache-tomcat-6.0.20 from <a href=\"http:\/\/tomcat.apache.org\/\">http:\/\/tomcat.apache.org<\/a>. Create 3 instances of tomcat named tomcatA, tomcatB with following configuration in conf\/server.xml.<\/p>\n<p>Uncomment the following entry in server.xml in all the instances of tomcat.<\/p>\n<pre>&lt;!--<br \/>&lt;Cluster className=\"org.apache.catalina.ha.tcp.SimpleTcpCluster\"\/&gt;<br \/>--&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p>Define the HTTP, AJP Connector, Shutdown ports for all the tomcat instances as below,<\/p>\n<p>&nbsp;<\/p>\n<p><strong>tomcatA<\/strong><\/p>\n<table width=\"400\" border=\"1\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"200\">HTTP<\/td>\n<td valign=\"top\" width=\"200\">8081<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"200\">Shutdown<\/td>\n<td valign=\"top\" width=\"200\">8105<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"200\">AJP Connector<\/td>\n<td valign=\"top\" width=\"200\">8109<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"200\">jvmRoute<\/td>\n<td valign=\"top\" width=\"200\">tomcatA<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p><strong>tomcatB <\/strong><\/p>\n<table width=\"400\" border=\"1\" cellspacing=\"0\" cellpadding=\"2\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"200\">HTTP<\/td>\n<td valign=\"top\" width=\"200\">8082<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"200\">Shutdown<\/td>\n<td valign=\"top\" width=\"200\">8205<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"200\">AJP Connector<\/td>\n<td valign=\"top\" width=\"200\">8209<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"200\">jvmRoute<\/td>\n<td valign=\"top\" width=\"200\">tomcatB<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p>Deploying web application in all tomcat instances:<\/p>\n<p>&nbsp;<\/p>\n<p>Deploy the Hello world JSP web application into all the tomcat instances, Make your HelloWorld.jsp with following content to feel the load balancing and session replication,<\/p>\n<p>&nbsp;<\/p>\n<p><strong>tomcatA \u2013 hello.jsp<\/strong><\/p>\n<p>&nbsp;<\/p>\n<pre>&lt;%<br \/>session.setAttribute(\u201cname\u201d , \u201cbala\u201d);<br \/>%&gt;<br \/>From tomcatA - Name from session - &lt;%= session.getAttribute(\u201cname\u201d); %&gt;<br \/>Session ID - &lt;%= session.getID() %&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>tomcatB \u2013 hello.jsp<\/strong><\/p>\n<p>&nbsp;<\/p>\n<pre>From tomcatB - Name from session - &lt;%= session.getAttribute(\u201cname\u201d); %&gt;<br \/>Session ID - &lt;%= session.getID() %&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p><em>&lt;distributable\/&gt;<\/em> tag should be defined in web.xml of your application, so that session replication will be supported by the web container.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>web.xml<\/strong><\/p>\n<p>&nbsp;<\/p>\n<pre>&lt;webapp&gt;<br \/>\u2026<br \/>..<br \/>&lt;distributable\/&gt;<br \/>..<br \/>..<br \/>&lt;\/webapp&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p>Configuring JK Connector for routing request to Tomcat from Apache Server:<\/p>\n<p>&nbsp;<\/p>\n<p>Download JK connector 1.2.8 from <a href=\"http:\/\/tomcat.apache.org\/connectors-doc\">http:\/\/tomcat.apache.org\/connectors-doc<\/a> and place mod_jk-1.2.28-httpd-2.2.3.so in modules\/ directory of Apache server.<\/p>\n<p>&nbsp;<\/p>\n<p>Add following configuration to httpd.conf file of Apache server,<\/p>\n<p>&nbsp;<\/p>\n<pre>LoadModule jk_module modules\/mod_jk-1.2.28-httpd-2.2.3.so<br \/>JkWorkersFile C:\\cluster\\workers.properties<br \/>JkLogFile \"logs\/mod_jk.log\"<br \/>JkLogLevel trace<br \/>JkMount \/cluster loadbalancer<br \/>JkMount \/cluster\/* loadbalancer<\/pre>\n<p>&nbsp;<\/p>\n<p>workers.properties should have the details about the tomcat instances which we have created as below,<\/p>\n<p>&nbsp;<\/p>\n<pre>workers.tomcat_home=\/tomcatA<br \/>workers.java_home=$JAVA_HOME<br \/>ps=\/<br \/>worker.list=tomcatA,tomcatB,loadbalancer<br \/>worker.tomcatA.port=8109<br \/>worker.tomcatA.host=localhost<br \/>worker.tomcatA.type=ajp13<br \/>worker.tomcatA.lbfactor=1<br \/>worker.tomcatB.port=8209<br \/>worker.tomcatB.host=localhost<br \/>worker.tomcatB.type=ajp13<br \/>worker.tomcatB.lbfactor=1<br \/>worker.loadbalancer.type=lb<br \/>worker.loadbalancer.balanced_workers=tomcatA,tomcatB<br \/>worker.loadbalancer.sticky_session=1<\/pre>\n<p>&nbsp;<\/p>\n<p>Now restart the Apache Server, TomcatA and TomcatB instances and access the HelloWorld application via URL, <a href=\"http:\/\/localhost\/Helloworld\/hello.jsp\">http:\/\/localhost\/Helloworld\/hello.jsp<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<p>Now you can see the session created by tomcatA will available in tomcatB also when accessing<\/p>\n<p>the above URL repeatedly.<\/p>\n","protected":false},"excerpt":{"rendered":"\n<p>In this post I will describe how to implement a functional Tomcat cluster with load balancing and failover<\/p>\n<p>I did a great deal of research trying to get this environment working. There are a number of good tutorials for simple Tomcat clustering and load balancing. I was unable to find an example that was [&#8230;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21],"tags":[],"_links":{"self":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/1238"}],"collection":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1238"}],"version-history":[{"count":3,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/1238\/revisions"}],"predecessor-version":[{"id":1244,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/1238\/revisions\/1244"}],"wp:attachment":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1238"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1238"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1238"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}