A Load Balancing Daemon

The goal is to distribute incoming requests among a bunch of Web servers.

Various Methods

Specialists
Distinct servers for graphics, text, CGI, etc.
Redirection daemon
Perl script redirects incoming requests to randomly-chosen servers.
DNS round-robin
Multiple A records in DNS authority table
      www.web.org A  192.168.9.1
      www.web.org A  192.168.9.2
      www.web.org A  192.168.9.3
      www.web.org A  192.168.9.4
      www.web.org A  192.168.9.5
      

Script I.4.1: Load Balancing Web Redirector

Does everything a real Web server does, except service requests.

 #!/usr/local/bin/perl
 
 # list of hosts to balance between
 @HOSTS = qw/www1.web.org www2.web.org www3.web.org www4.web.org/;
 
 use IO::Socket;
 $SIG{CHLD} = sub { wait() };
 $ENV{'PATH'}='/bin:/usr/bin';
 chomp($hostname = `/bin/hostname`);
 
 # Listen on port 80
 $sock = IO::Socket::INET->new(Listen  => 5,
 			      LocalPort => 80,
 			      LocalAddr => $hostname,
 			      Reuse     => 1,
 			      Proto    => 'tcp');
 die $@ unless $sock;
 
 # become "nobody"
 $nobody  = (getpwnam('nobody'))[2]  || die "nobody is nobody";
 $nogroup = (getgrnam('nogroup'))[2] || die "can't grok nogroup";
 ($<,$() = ($>,$)) = ($nobody,$nogroup); # get rid of root privileges!
 ($\,$/) = ("\r\n","\r\n\r\n");          # CR/LF on output/input
 
 # Go into server mode
 close STDIN; close STDOUT; close STDERR;
 
 # prefork -- gee is that all there is to it?
 fork() && fork() && fork() && fork() && exit 0;
 
 # start accepting connections
 while (my $s = $sock->accept()) {
     do { $s->close; next; } if fork();
     my $request = <$s>;
     redirect($1,$s) if $request=~/(?:GET|POST|HEAD|PUT)\s+(\S+)/;
     $s->flush;
     undef $s;
     exit 0;
 }
 
 sub redirect {
     my ($url,$s) = @_;
     my $host = $HOSTS[rand(@HOSTS)];
     print $s "HTTP/1.0 301 Moved Temporarily";
     print $s "Server: Lincoln's Redirector/1.0";
     print $s "Location: http://${host}${url}";
     print $s "";
 }

What it Looks Like

% telnet localhost 80
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET /index.html HTTP/1.0

HTTP/1.0 301 Moved Temporarily
Server: Lincoln's Redirector/1.0
Location: http://www3.web.org/index.html

Connection closed by foreign host.

<< Previous Contents >> Next >>

Lincoln D. Stein, lstein@cshl.org
Cold Spring Harbor Laboratory
Last modified: Mon Aug 17 10:45:03 EDT 1998