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