just out of the sake of boredom and insanity, I was asked to setup load balancing here for a server at work. and I instantly fired up a pico session and starting hacking away at some perl :)
now, what they actually wanted me to do was email a guy and setup a round robin DNS, but of course, in my delirious, sick state I began a script to do load balancing in perl.
here's what I hacked out: (I plan on developing this to be a really kick ass system, but right now, its basic and it works)
#!/usr/bin/perl
# This is going to be fun..
# anyways.. code by me..
# Brad Lhotsky
# <brad@divisionbyzero.net>
#
use Socket;
use Symbol;
use Time::localtime;
use strict;
my $port = 8080;
my %CONF = {};
my $cfgfile = "balance.cfg";
my $DATADIR = "/home/blhotsky/code/load/data/";
%CONF = &readconf($cfgfile);
my ($crap,$things);
foreach $crap (keys(%CONF))
{
print "$crap\n";
foreach $things (@{$CONF{$crap}})
{
print "\t$things\n";
}
}
socket(SERVER, AF_INET, SOCK_STREAM, getprotobyname('tcp')) || die $!;
setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, 1); select SERVER; $|++;
+select('stdout');
my $sin = sockaddr_in($port, INADDR_ANY);
bind(SERVER, $sin) || die $!;
listen(SERVER, SOMAXCONN);
while(1)
{
my $socket = gensym();
accept($socket, SERVER);
select $socket; $|++; select('stdout');
my $get = <$socket>;
chomp $get;
my ($null, $url,$opts);
($null, $url,$null) = split(/\s/,$get);
($url, $opts) = split(/\?/, $url);
&print_header($socket);
my $redirect = &balance($url);
if($opts) { $redirect .= "?$opts"; }
$redirect .= "\n\n";
print $socket $redirect;
close $socket;
}
sub readconf {
my $file = shift;
die "no conf file!\n" if !$file;
open(FILE, "< $file") || die "could not open $file\n";
my %HASH;
my $link;
while(<FILE>)
{
s/^\s+//;
chomp;
next if /^$/;
next if /^\#/;
my($line,$comment) = split /\#/, $_;
if(($line !~ /^:/) && !$link) { next; }
if($line =~ /^:(.*)/) { $link = $1; $HASH{$link} = ();
+ next; }
# If we get here, we need to push stuff into the hashe
+s anon array.
$line =~ s/\s+$//;
push @{$HASH{$link}}, $line;
}
return %HASH;
}
sub balance {
my $url = shift;
if($url eq '/') { $url = "index.html"; }
else { $url =~ s%^/%%; }
if(!$url) { die "dammit no url to go to!\n"; }
my $redirect;
my $index = &getindex($url);
if($CONF{$url}) { $redirect = $CONF{$url}->[$index]; }
else { $redirect = "http://divisionbyzero.net/~trilex/index.ht
+ml"; }
$redirect = "Location: $redirect\n\n";
return $redirect;
}
sub print_header {
my $socket = shift;
if(!$socket) { die "no socket dumbass!\n"; }
my $date = "Date: " . ctime() . " EST\n";
my $headers = "HTTP/1.1 302 Found\n" . $date . "Server: Funky
+Load Balancer/0.0.1 (Unix) Perl\n" . "Connection: close\n";
print $socket $headers;
}
sub getindex {
my $url = shift;
if(!$url) { die "dammit no url to go to!\n"; }
open(DATA, "<$DATADIR/$url") || sub { &datahandle($url); retur
+n 0; };
my $line = <DATA>;
close DATA;
chomp $line;
$line =~ s/\D+//g;
&datahandle($url,$line);
return $line;
}
sub datahandle {
my $url = shift;
my $num = shift;
my $file = "$DATADIR/$url";
$num++;
if($num > $#{$CONF{$url}}) { $num = "0"; }
if(!$url) { die "how the hell did this die?"; }
open(DATA, ">$file") || die "this is not good no permissions i
+n $DATADIR\n";
print DATA "$num\n";
close DATA;
}
and here's the config file:
#######################
# Load Balancing conf file.
# format:
# :file # absolute path from the server dir
# http://some.domain.com/path/to/file
# http://some.domain2.com/path/to/file
# :file2
# http://some.domain.com/path/to/file2
# http://some.domain2.com/path/to/file2
:dbz
http://divisionbyzero.net/index.html
http://spark.divisionbyzero.net/index.html
:funky
http://ackers.net/index.html
http://realms.divisionbyzero.net/index.html
-brad..