Load Balancing with PEN

How many times have you had a very expensive load balancing pair in front of your network and some service behind them that needed to use another load balanced service in the back end? Now you can always throw caution to the wind and allow the big boys up front to do the load balancing for your service and create that horrible path of data movement that nobody really wants. It will work, but it immediately doubles up the load on your front end and it just isn’t linear and pretty. If you’re one of the privileged few, you could have a second set of expensive load balancers in the private space of your network to use precisely for this purpose. If you’re not, let me introduce PEN.

As described by the creators:

This is pen, a load balancer for “simple” tcp based protocols such as http or smtp. It allows several servers to appear as one to the outside and automatically detects servers that are down and distributes clients among the available servers. This gives high availability and scalable performance.

PEN Site

 

 

So in the case above, we want our Web Servers to hit the SOLR servers in a round robin fashion as we don’t care if anything maintains state.  Just get the info and stick it in the site.  The big difference between PEN and some other Load Balancers you may be used to, is that it is just a single command line process.  Everything you need to start your pool happens in a single line.  You can download PEN here, or you can use the following repo on RHEL systems:

 

rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm

 

Once installed you need to identify the following variables to create your pool:

1.) Local source port

2.) Number of servers in your pool

3.) Destination ports on servers in your pool

4.) Details of your control host (this can be used to issue commands to PEN on the fly)

 

In the example above, we want to create a local port on our web servers that when hit, will request services from the 2 SOLR Servers.  Our command line will look like this:

 

/usr/bin/pen -S 2 -C localhost:10081 -r 8983 10.1.1.10:8983 10.1.1.11:8983

 

We are telling pen that (-S) we have 2 servers, (-C) our control server is at port 10081 on the localhost, (-r) we want to perform round robin load balancing on local port 8983 and our 2 servers 10.1.1.10 and 10.1.1.11 will be accepting requests for this pool on port 8983.

 

I typically run these processes from startup with the script below. You can easily take this script and modify it to meet your needs. There are also parameters in the script to set the number of maximum concurrent connections, the log file to use and where to store the PID. Here’s the output from the PEN manpage with a full list of options.

startup script:

#!/bin/bash
#
# Pen: Starting Pen
#
# chkconfig: 345 93 92
# description: Simple load-balancer
# processname: pen. /etc/rc.d/init.d/functions
pen=”/usr/local/bin/pen”
lockfile=”/var/lock/subsys/pen”
prog=”pen”
RETVAL=0

# PID file
PID=/var/run/pen.pid-80
# log file
LOGFILE=/var/log/pen.log
# control port
CONTROL=localhost:10080
# max connections
MAX_CONNECTIONS=500
# listening port
PORT=8983
# number of backend servers
SERVERS=2
# IP of server #1
SERVER1=10.1.1.10:8983
# IP of server #2
SERVER2=10.1.1.11:8983

start() {
echo -n $”Starting $prog: ”
daemon $pen -x $MAX_CONNECTIONS -S $SERVERS -p $PID -l $LOGFILE -C $CONTROL -r $PORT $SERVER1 $SERVER2
RETVAL=$?
echo
[ $RETVAL = 0 ] && touch $lockfile
return $RETVAL
}
stop() {
echo -n $”Stopping $prog: ”
kill -9 `cat $PID`
rm $PID
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f $lockfile
return $RETVAL
}
case “$1″ in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status $pen
;;
*)
echo “Usage: $prog {start|stop|restart|status}”
exit 1
esac

exit $?

 

There’s also some cute tricks you can do with the control port. Some of the more useful ones are:

 
penctl manpage

# Return local address and port pen listens to for incoming client connections.[root]# penctl localhost:10080 listen
8983
[root]## Write a summary of the current mode of operation. The listed modes are block, delayed_forward, hash, roundrobin, stubborn.

[root]# penctl localhost:10080 mode
no block no delayed_forward no hash roundrobin no stubborn no weight no prio
[root]#


# List address, port and max number of simultaneous connections for each remote server.

[root]# penctl localhost:10080 servers
0 addr 10.1.1.10 port 8984 conn 0 max 0 hard 0 weight 0 prio 0 sx 94498898 rx 6249894741
1 addr 10.1.1.11 port 8984 conn 0 max 0 hard 0 weight 0 prio 0 sx 94491331 rx 6237353264
[root]#

 

 

 

1 Comments

  1. I had to add the following line to get this working on a Centos 6.2 box

    . /etc/init.d/functions

0 Trackbacks

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>