(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