Deploying Network Dispatcher
Copyright 2002, 2003 Andy Barclay
OpenContent License (OPL)
Notes
======
1. Detailed documentation can be found at www.redbooks.ibm.com
(search for performance pack)
2. See the section at the bottom called "Looking for Updates"
3. Upgrade the JVM to at least version 1.1.7
# pkgrm SUNWjvman SUNWjvjit SUNWjvdem SUNWjvdev SUNWjvrt
# pkgadd -d . SUNWjvrt SUNWjvjit SUNWjvman
Overview
========
Network Dispatcher is a Load Balancer product from IBM.
I have used the Network dispatcher for the following purposes:
-hides multiple web servers behind a single address
-route incoming http/https packets to several web servers
-periodically check availability of the web servers, removing
any that fail the check from the list of servers eligible to
receive those packets
The IBM Network Dispatcher supports a high-availability config
This document assumes we have two webservers and we would like to distribute
the load across them.
web server #1: web1.unixpeople.com
web server #2: web2.unixpeople.com
cluster address: www.unixpeople.com
One set of load balancer machines can serve any number of cluster addresses
(web sites)
Installing Network Dispatcher
=============================
On Solaris
==========
Login to web2 as root.
stop netscape admin server (/etc/init.d/netscapeadminserver stop)
stop netscape server (/etc/init.d/netscapeserver stop)
install the network dispatcher component of the performance pack
extract the gzip'd tar file someplace where there is space
# cd /tmp
# gzip -dc /mnt/wspp*gz |tar xf -
-install the ibm network dispatcher
# cd /tmp/wspp2.0/sun/nd
# pkgadd -d .
(when asked what packages to install, type in:10,11,6,5,4,9,8,7)
(when install is complete, type: q)
-change the default interface name if required
edit /opt/eND/dispatcher/ibmnd.conf and change "le" to "hme"
Login to web1 as root.
stop netscape admin server (/etc/init.d/netscapeadminserver stop)
stop netscape server (/etc/init.d/netscapeserver stop)
install the network dispatcher component of the performance pack
extract the gzip'd tar file someplace where there is space
# cd /tmp
# gzip -dc /mnt/wspp*gz |tar xf -
-install the ibm network dispatcher
# cd /tmp/wspp2.0/sun/nd
# pkgadd -d .
(when asked what packages to install, type in:10,11,6,5,4,9,8,7)
(when install is complete, type: q)
-change the default interface name if required
edit /opt/eND/dispatcher/ibmnd.conf and change "le" to "hme"
Automating the startup of the load balancer
===========================================
On web1, create a file called /etc/init.d/loadbalancer
*****************
#!/bin/sh
#@(#) Network Dispatcher startup script version 3.2
# AWB - ensure that any shells spawned from here will not complain
unset ENV
# AWB - this is the instance of the network interface to use
INSTANCE=1
version=`uname`
case "$version" in
SunOS)
# AWB - this is the time the script will sleep before starting
# to prevent kernel panics at boot time
DELAY=60
INSTALLDIR=/opt/nd
#grab the interface type from ibmnd.conf
interface=`cat $INSTALLDIR/dispatcher/ibmnd.conf |
head -1 |awk '{print $1}'`
;;
AIX)
# AWB - this is the time the script will sleep before starting
# to prevent kernel panics at boot time
DELAY=0
INSTALLDIR=/usr/lpp/nd
interface=en
;;
*)
echo "$0 does not recognize the Operating System" >&2
exit 1
;;
esac
# AWB this function will return the IP address of this server
getlocalip()
{
#now get the ip address of this server
# NOTE: assumes the first instance of the interface is being used
ifconfig ${interface}${INSTANCE} |grep inet |awk '{print $2}'
}
case $1 in
start)
cd $INSTALLDIR
nohup $0 starting &
sleep 2
;;
starting)
sleep $DELAY
echo "starting the network dispatcher server"
ndserver start
sleep 5
echo "starting the executor"
ndcontrol executor start
NFA=`getlocalip`
echo "Loading the non-forwarding address to $NFA"
ndcontrol executor set nfa $NFA
#start the manager
ndcontrol manager start
for i in $INSTALLDIR/clusters/*
do
# AWB - ensure that all this stuff runs in a subshell
(
# source the cluster information
. $i
# only create the cluster if it doesn't yet exist
if ndcontrol cluster status $CLUSTER |grep "^Error" >/dev/null
then
echo "Loading CLUSTER address: $CLUSTER"
ndcontrol cluster add $CLUSTER
fi
echo "Creating ports for CLUSTER: $CLUSTER"
ndcontrol port add $CLUSTER:$PORT stickytime $STICKYTIME
x=1
SERVER=`eval echo '$SERVER'${x}`
while [ -n "$SERVER" ]
do
echo "Adding server machine $SERVER to $CLUSTER"
ndcontrol server add $CLUSTER:$PORT:$SERVER
x=`expr $x + 1`
SERVER=`eval echo '$SERVER'${x}`
done
# only start the advisor if the proto var is set
# and the advisor is not currently started for that port
if [ -n "$PROTO" ] &&
ndcontrol advisor status $PROTO $PORT |
grep "^Error" >/dev/null
then
echo "Starting advisor on port $PORT ..."
ndcontrol advisor start $PROTO $PORT
fi
# AWB only setup the heartbeat if its not setup already
) # AWB end of the subshell
done
# set the proportions to also be aware of advisors
ndcontrol manager proportions 48 48 4 0
ndcontrol manager smoothing 10.0
. $INSTALLDIR/clusters/.main_config
if [ $NFA = $NDPRIMARY ]
then
ndcontrol highavailability heartbeat add \
$NDPRIMARY $NDBACKUP
ndcontrol highavailability backup add primary manual 32777
else
ndcontrol highavailability heartbeat add \
$NDBACKUP $NDPRIMARY
ndcontrol highavailability backup add backup manual 32777
fi
;;
stop)
ndcontrol highavailability back delete
ndcontrol manager stop
ndcontrol executor stop
ndserver stop
;;
*)
echo "Usage: $0 start|stop" >&2
exit 2
;;
esac
echo "Script complete"
exit 0
*****************
Link this file into the startup dir and the shutdown dir.
web1:/# ln -s /etc/init.d/loadbalancer /etc/rc3.d/S30loadbalancer
web1:/# ln -s /etc/init.d/loadbalancer /etc/rc0.d/K10loadbalancer
Each time the Load Balancer changes state, a script gets executed
State Change Script
------------------------------
Active -> Standby goStandby
Standby -> Active goActive
shutdown goInOp
There is a script that generates these scripts for you based on the
contents of the files in /opt/nd/clusters
Create this script
# mkdir /opt/nd/clusters
# vi /opt/nd/clusters/.buildGoScripts.sh
****************************
#!/bin/sh
OS=`uname`
case "$OS" in
SunOS)
INSTALLDIR=/opt/nd
# AWB - find out what the interface type is from ibmnd.conf
interface=`cat $INSTALLDIR/dispatcher/ibmnd.conf |
head -1 |awk '{print $1}'`
ETHER=`ifconfig -a |awk '/ether/ {print $2}'`
;;
AIX)
INSTALLDIR=/usr/lpp/nd
interface=en
;;
esac
# AWB - no assume it is instance 0 of that type of interface
interface=${interface}0
# AWB - remove all content from the existing go Scripts
# and install a standard header
for i in $INSTALLDIR/dispatcher/bin/go*
do
[ -f $i ] && cat > $i <>$INSTALLDIR/dispatcher/logs/failover.log 2>&1
# and record the current date and the script that is running
echo "Running $i at \`date\`"
#
EOT
done
# this variable is incremented with each cluster
instance=1
for i in $INSTALLDIR/clusters/*
do
#AWB ensure this gets sourced in a subshell
(
# source the cluster information
. $i
#stick all the cluster addresses in a temp file
echo $CLUSTER $NETMASK >>/tmp/clusters.$$
)
done
# now remove any duplicates from the cluster file
cat /tmp/clusters.$$ | sort -u | while read CLUSTER NETMASK
do
case "$OS" in
SunOS)
#populate the goActive script
cat >> $INSTALLDIR/dispatcher/bin/goActive <> $INSTALLDIR/dispatcher/bin/goInOp <> $INSTALLDIR/dispatcher/bin/goStandby <> $INSTALLDIR/dispatcher/bin/goActive <> $INSTALLDIR/dispatcher/bin/goInOp <> $INSTALLDIR/dispatcher/bin/goStandby <0
add this number to the timing or replace timing with the number depending
on the flag.
flag=true means replace value
flag=false means "add to value"
NOTE: flag is the last argument on the constructor
Sample Classes
--------------
wxyz.java - side stream
nikko.java - couples port 80 and port 443
adv_was.java
ndadvisor.java - servlet