I want to use apache load balancer so that one tomcat server is primary, and the secondary server is online only if the first server is down. how can this be done?
If you're only going to do load balancing, I would recommend something more lightweight than Apache, such as HAproxy, but lets assume that you're going to go with apache.
There are several methods for load balancing, so you should spend a little bit of time getting acquainted with them. There is an excellent article available by Willy Tarreau called Making applications scalable with Load Balancing that is worth your time to read.
There are a couple of tools for making Apache a load balancer, and maybe the easiest (that I know of) is by using mod_proxy_balancer. The only problem with this is that it doesn't appear to do failover load balancing (which is what you want: high availability, rather than true load balancing).
Since you're using Tomcat, why not use mod_jk, the Apache tomcat connectors?
Assume for a second that we're on a Redhat-based system (I'm using CentOS 5.5) that is configured to compile things (for instance, has gcc and the appropriate libraries (this isn't a good idea on production systems. This is not the time or place to discuss RPM packaging, though)
yum install httpd httpd-devel
This will install Apache along with the development stuff for making modules, and the configuration directory will be /etc/httpd/
The current (20110130) Tomcat Connectors are 1.2.31 (but you can check for the latest here), so download them:
Extract, compile, and install them:
tar zxvf tomcat-connectors-1.2.31-src.tar.gz cd tomcat-connectors-1.2.31-src/native ./configure --with-apxs=/usr/sbin/apxs make sudo make install
Verify that mod_jk.so was installed:
ls -al /etc/httpd/modules/mod_jk.so -rwxr-xr-x 1 root root 903072 Jan 30 15:21 /etc/httpd/modules/mod_jk.so
Now, we get to actually configure it.
# This actually tells apache to load the module we built LoadModule jk_module modules/mod_jk.so # This file holds the instructions for which servers the proxy will be talking to JKWorkersFile /etc/httpd/conf.d/workers.properties # This is (obviously) the logfile that it will write to. Change to whatever you want JKLogFile /var/log/httpd/mod_jk.log # Simplistically, we'll set up a virtualhost that listens on all IPs on port 80. # HTTPS is left as an exercise for the reader NameVirtualHost *:80 <VirtualHost *:80> ServerAdmin email@example.com ServerName thedomainnameoftheproxy.com # The following line says "send anything to the JK Worker named MyProxyCluster" JKMount /* MyProxyCluster </VirtualHost> #EOF
Alright, that tells Apache that we want to use mod_jk, that we want to use a file called /etc/httpd/conf.d/workers.properties, and that we have one virtualhost where everything is sent to the workers. Great, now lets configure the workers. Edit /etc/httpd/conf.d/workers.properties:
# We're telling mod_jk which workers it needs to look for. We're going to define # a total of 3 workers: MyProxyCluster (the load balancer job), worker1, and worker2 # (the two backend servers) worker.list=MyProxyCluster worker.worker1.port=8009 worker.worker1.host=hostname.or.ip.of.1st.tomcat.server # ajp13 means Apache JServ Protocol version 1.3, and is apparently universal worker.worker1.type=ajp13 worker.worker1.lbfactor=1 # When worker1 dies, we're going to want it to go to worker2 worker.worker1.redirect=worker2 ### End of worker1 config # repeat the same things for worker2 worker.worker2.port=8009 worker.worker2.host=hostname.of.ip.of.2nd.tomcat.server worker.worker2.type=ajp13 worker.worker2.lbfactor=1 # Disable worker2 except when it fails over worker.worker2.activation=disabled # make the actual load balancer worker that we referenced in the beginning worker.MyProxyCluster.type=lb worker.MyProxyCluster.balance_workers=worker1,worker2 # EOF
Now, we have two actual workers, and one virtual load balancer for them. You can now start Apache:
service httpd start
Test it out by browsing to the machine, and it should go to the first tomcat server. You should be able to verify this by watching /var/log/httpd/mod_jk.log (or wherever you pointed it).
Here is a much simpler solution using AJP instead of JK:
<Proxy balancer://cluster> BalancerMember ajp://127.0.0.1:8009 route=jvm1 status=-D BalancerMember ajp://127.0.0.2:8009 route=jvm2 status=+H </Proxy> ProxyPass /app balancer://cluster/app
There are quite a few more configuration properties you can set, such as differential load factors if you have more backends, different balancing algorithms, balancer sets, etc: see the Apache mod_proxy documentation, but the above does exactly what you specified. -D means 'not disabled' and +H means 'hot standby'. And you can swap them at runtime too.
You just need to run two Tomcats, with AJP connectors running on port 8009 with address="127.0.0.1", address="127.0.0.2" etc, as many as you need, with
<Engine jvmRoute="jvm1"> and
<Engine jvmRoute="jvm2"> respectively. Note the economy of ports: you can do the same with the shutdown port too. Throw away anything in the Tomcat configuration referring to JK, mod_jk, etc. You don't need those frightful
workers.properties files either. You can also throw away all the HTTP and HTTPS connectors and terminate inbound SSL at the Apache HTTPD, which gives you much finer-grained control over SSL.