(RADIATOR) new AuthBy PENDINGREQUESTS
Jeremy Hinton
jgh at visi.net
Mon Sep 16 12:04:24 CDT 2002
Following is a new AuthBy module i put together to fix a specific problem
here. I was using Radius to authenticate off our LDAP server, but the
problem was the LDAP server introduced a 2 second delay when the password
was invalid (to prevent password hack attempts). Since AuthBy LDAP is
synchronous, this was causing problems. The following module is a variant
on AuthBy ROUNDROBIN. It keeps track of how many pending requests (requests
for which a response has not yet been received) each host has, and picks
the host with the least. Here, running one master instance of radius with
AuthBY PENDINGREQUESTS rolling across 3 backend servers with AuthBy LDAP
(all on one machine), it works like a charm. most requests go to the first
backend server, if it pauses on an invalid login, request go to the second
one until the first starts responding again. While the best solution would
be to just make AuthBy LDAP asynchronous, i'm not that good a programmer
;). Enjoy!
- jeremy
# AuthPENDINGREQUESTS.pm
#
# Object for handling Authentication with remote radius servers
# This subclass of AuthBy RADIUS implements host selection by
# comparing pending requests queue size, including backoffs for
# failed hosts
#
# As a request is allocated to a valid Host, the pendingRequests
# value for that host is incremented. Also overloaded succeeded()
# and failed() to correctly decrement the request value.
#
# Author: Jeremy Hinton (jhinton at visi.net)
package Radius::AuthPENDINGREQUESTS;
@ISA = qw(Radius::AuthRADIUS);
use Radius::AuthRADIUS;
use strict;
#####################################################################
# Choose the next host for the PENDINGREQUESTS algorithm
sub chooseHost
{
my ($self, $fp, $p) = @_;
my ($valid_hosts, $host, $selectedhost) = 0;
my ($least_requests) = 65535; # arbitrary high number
my $time = time;
# See if there is a host with a chance of being selected
foreach $host (@{$self->{Hosts}})
{
next if $time < $host->{backoff_until};
if ($host->{backoff_until}) { # reset pendingRequests to 0
$host->{backoff_until} = 0;
$host->{pendingRequests} = 0;
}
$valid_hosts++;
}
if ($valid_hosts == 0) # No available hosts
{
$self->log($main::LOG_WARNING,
"ProxyAlgorithm PENDINGREQUETS Could not find a working " .
"host to proxy to", $p);
return; # None found
}
# Check how many pending requests we have with each host. Return the
# to the one with the least, and increment its pendingRequests counter
foreach $host (@{$self->{Hosts}})
{
next if $time < $host->{backoff_until};
if ($host->{pendingRequests} <= $least_requests)
{
$least_requests = $host->{pendingRequests};
$selectedhost = $host;
}
}
$selectedhost->{pendingRequests}++;
return $selectedhost;
}
sub succeeded
{
my ($self, $host, $p, $op, $sp) = @_;
$host->{pendingRequests}--;
}
sub failed
{
my ($self, $host, $fp, $p) = @_;
$host->{pendingRequests}--;
Radius::AuthRADIUS::failed(@_);
}
1;
===
Archive at http://www.open.com.au/archives/radiator/
Announcements on radiator-announce at open.com.au
To unsubscribe, email 'majordomo at open.com.au' with
'unsubscribe radiator' in the body of the message.
More information about the radiator
mailing list