This is simply one of many different configurations of a ModBackhand cluster and is how I currently have mine setup.
In this configuration we have a single machine at the front that has a stripped down version of Apache that will do all the load balancing and not service requests itself. Behind the balancer is the cluster of application servers, these will have the heavier Apache (ie, PHP, mod_perl, mod_jk/Tomcat) and do all the actual serving of requests.
In this example though we have a single point of failure, which is the balancer, this can be fixed by having a second backup balancer ready to take over (see HighAvailability).
(Note: mod_backhand will only work on Unix machines with Apache 1.3.x)
If you are using apache one you can apt-get install libapache_mod_backhand, unfortunately mod_backhand does not seem to be packaged for Apache2 in sarge.
After it's compiled/installed you need to make sure it's enabled in Apache, check the following lines appear somewhere in your httpd.conf
LoadModule? backhand_module libexec/apache/mod_backhand.so
AddModule? mod_backhand.c
Make sure the !AddModule? line goes above any other 3rd party extension !AddModule? lines (like PHP/mod_jk/mod_perl)
<!IfModule? mod_backhand.c>
UnixSocketDir? /var/backhand/
Make sure /var/backhand exists and is writeable by the user Apache runs as
MulticastStats? 10.58.4.1 239.255.221.20:4445,1
This line tells ModBackhand we want to advertise ourselves as 10.58.4.1 to the multicast address 239.255.221.20 port 4445 with a timeout of 1 second
AcceptStats? 10.58.4.0/24
Because all ModBackhand enabled servers will broadcast information we want to know which information we should listen to, so accept messages from our backend servers on the network 10.58.4.0/24
</!IfModule?>
Having a <Directory> block will enable ModBackhand balancing for all requests to files in that directory, it doesn't have to be your DocumentRoot? and it can also be a <Files .php|.asp> or <Location> block. You can practically balance anything Apache will understand.
<Directory /usr/local/www/htdocs/>
AllowOverride? None
Options None Order allow,deny Allow from all
Backhand removeSelf
Because this server is simply a balancer we don't want to consider ourself as a valid server when selecting a candidate
Backhand byAge 6
We don't want to send a request to a server we haven't heard from in 6 seconds. This provies some fault tolerance as the request won't be directed to a dead candidate.
Backhand byRandom
Randomly choose a server from remaining pool.
Backhand byLogWindow
This does something I don't quite understand yet, but it's good to have
Backhand byLoad
Decide which candidate is best from the load on that server
</Directory>
If your balancer is serving multiple sites, put the above in a <VirtualHost?> block, otherwise it doesn't matter. These are not the only candidancy functions available, for a list of the rest see the ModBackhand website.
First we enable ModBackhand
<!IfModule? mod_backhand.c>
UnixSocketDir? /var/backhand/
MulticastStats? 10.58.4.2 239.255.221.20:4445,1
AcceptStats? 10.58.4.0/24
</!IfModule?>
Again, make sure /var/backhand exists and is writeable by the Apache user. These options can also go in a <VirtualHost?> block or not. However! Because ModBackhand is proxying these requests you CANNOT use NameBased? Virtual Hosting on sites that are part of the cluster. You CAN use IP Based Virtual Hosting which means you would need a block (like above) for each !VirtualHost? with a different adress for !MulticastStats?. Don't forget to make sure your !DocumentRoot? is right for this !VirtualHost? or the general configuration.
The cluster should be working! If you want to see the status of your cluster, put the following in your balancers httpd.conf
<!VirtualHost? 10.58.4.1>
DocumentRoot? /usr/local/www/data
<Location "/backhand/">
SetHandler? backhand-handler
</Location>
</!VirtualHost?>
Then browse to http://10.58.4.1/backhand/ and it'll give you a status map.
You now have a clustered website, but you still have storage and a database to worry about!
One page links to ModBackhandExample: