From 95102e68c5198f1421c36e73b0b688ae34a01739 Mon Sep 17 00:00:00 2001 From: Richard Siddall Date: Thu, 13 Feb 2014 21:42:56 -0500 Subject: [PATCH 1/5] Added Peter Eisch's load checking plugin, see: http://www.nntp.perl.org/group/perl.qpsmtpd/2006/01/msg4422.html, and Steve Kemp's alternative at: http://www.nntp.perl.org/group/perl.qpsmtpd/2008/03/msg7814.html --- plugins/loadcheck | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 plugins/loadcheck diff --git a/plugins/loadcheck b/plugins/loadcheck new file mode 100644 index 0000000..dd0493f --- /dev/null +++ b/plugins/loadcheck @@ -0,0 +1,74 @@ +#!/usr/bin/perl + +=head1 NAME + +loadcheck + +=head1 DESCRIPTION + +Only takes email transactions if the system load is at or below a +specified level. + +=head1 CONFIG + +max_load + + This is the 1 minute system load where we won't take transactions +if our load is higher than this value. (Default: 7) + +uptime + + The path to the command 'uptime' if different than the default. +(Default: /usr/bin/uptime) + +Example: + +loadcheck max_load 7 uptime /usr/bin/uptime + +=over 4 + +=head1 AUTHOR + +Written by Peter Eisch . + +=cut + +my $VERSION = 0.01; + +sub register { + my ($self, $qp, @args) = @_; + + %{$self->{_args}} = @args; + + $self->{_args}->{max_load} = 7 + if (! defined $self->{_args}->{max_load}); + + $self->{_args}->{uptime} = '/usr/bin/uptime' + if (! defined $self->{_args}->{uptime}); + + $self->register_hook("connect", "loadcheck"); +} + +sub loadcheck { + my ($self, $transaction) = @_; + + my $hiload = 0; + + my $cmd = $self->{_args}->{uptime}; + #10:33AM up 2:06, 1 user, load averages: 6.55, 3.76, 2.48 + # 12:29am 2 users, load average: 0.05, 0.05, 0.06 + # 12:30am up 5 days, 12:43, 1 user, load average: 0.00, 0.00, 0.00 + + my $res = `$self->{_args}->{uptime}`; + if ($res =~ /aver\S+: (\d+\.\d+)/) { + $hiload = $1; + } + + if ($hiload > $self->{_args}->{max_load}) { + $self->log(LOGERROR, "local load too high: $hiload"); + return DENYSOFT; + } + + return (DECLINED, "continuing with load: $hiload"); +} + From 04fc9327b7b41e42cf429d03ea71b2bcc9d175f0 Mon Sep 17 00:00:00 2001 From: Richard Siddall Date: Fri, 21 Mar 2014 09:40:01 -0400 Subject: [PATCH 2/5] Found the improved version of Peter Eisch's plugin attached to http://www.nntp.perl.org/group/perl.qpsmtpd/2006/03/msg4710.html. This includes caching of the system load and adds a cache_time config parameter. --- plugins/loadcheck | 69 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 13 deletions(-) mode change 100644 => 100755 plugins/loadcheck diff --git a/plugins/loadcheck b/plugins/loadcheck old mode 100644 new mode 100755 index dd0493f..3fe3f72 --- a/plugins/loadcheck +++ b/plugins/loadcheck @@ -9,6 +9,12 @@ loadcheck Only takes email transactions if the system load is at or below a specified level. +If this is running on a system that provides /kern/loadavg or +/proc/loadavg it will be used in stead of the 'uptime' command. + +Once a load value is determined, it is cached for a period of time. +See the cache_time below. + =head1 CONFIG max_load @@ -16,13 +22,20 @@ max_load This is the 1 minute system load where we won't take transactions if our load is higher than this value. (Default: 7) +cache_time + + A recently determined load value will be cached and used for the +assigned number of seconds. (Default: 10) + uptime - The path to the command 'uptime' if different than the default. + The path to the command 'uptime' if different than the default. (Default: /usr/bin/uptime) Example: +loadcheck cache_time 30 + loadcheck max_load 7 uptime /usr/bin/uptime =over 4 @@ -46,29 +59,59 @@ sub register { $self->{_args}->{uptime} = '/usr/bin/uptime' if (! defined $self->{_args}->{uptime}); + $self->{_args}->{cache_time} = 10 + if (! defined $self->{_args}->{cache_time}); + + $self->{_load} = -1; + $self->{_time} = 0; + $self->register_hook("connect", "loadcheck"); } sub loadcheck { my ($self, $transaction) = @_; - my $hiload = 0; + if (time() > ($self->{_time} + $self->{_args}->{cache_time})) { + # cached value expired - my $cmd = $self->{_args}->{uptime}; - #10:33AM up 2:06, 1 user, load averages: 6.55, 3.76, 2.48 - # 12:29am 2 users, load average: 0.05, 0.05, 0.06 - # 12:30am up 5 days, 12:43, 1 user, load average: 0.00, 0.00, 0.00 - - my $res = `$self->{_args}->{uptime}`; - if ($res =~ /aver\S+: (\d+\.\d+)/) { - $hiload = $1; + if ( -r '/kern/loadavg' ) { # *BSD + # contains fix-point scaling value + open(LD, "; + close LD; + my @vals = split(/ /, $res); + $self->{_load} = ($val[0] / $val[3]); + $self->{_time} = time(); + $self->log(LOGDEBUG, "/kern/loadavg reported: $self->{_load}"); + } elsif ( -r '/proc/loadavg' ) { # *inux + # contains decimal value + # contains fix-point scaling value + open(LD, "; + close LD; + $self->{_load} = (split(/ /, $res))[0]; + $self->{_time} = time(); + $self->log(LOGDEBUG, "/proc/loadavg reported: $self->{_load}"); + } else { + # the various formats returned: + #10:33AM up 2:06, 1 user, load averages: 6.55, 3.76, 2.48 + # 12:29am 2 users, load average: 0.05, 0.05, 0.06 + # 12:30am up 5 days, 12:43, 1 user, load average: 0.00, 0.00, 0.00 + + my $res = `$self->{_args}->{uptime}`; + if ($res =~ /aver\S+: (\d+\.\d+)/) { + $self->{_load} = $1; + $self->{_time} = time(); + $self->log(LOGDEBUG, "$self->{_args}->{uptime} reported: $self->{_load}"); + } + } } - if ($hiload > $self->{_args}->{max_load}) { - $self->log(LOGERROR, "local load too high: $hiload"); + if ($self->{_load} > $self->{_args}->{max_load}) { + $self->log(LOGERROR, "local load too high: $self->{_load}"); return DENYSOFT; } - return (DECLINED, "continuing with load: $hiload"); + return (DECLINED, "continuing with load: $self->{_load}"); } From 5df4dec48d3c335bd1ccbcc42b77af92999190da Mon Sep 17 00:00:00 2001 From: Richard Siddall Date: Fri, 21 Mar 2014 09:42:54 -0400 Subject: [PATCH 3/5] Bumped the plugin version number for the variant with caching. Fixed a typo in the perldoc. --- plugins/loadcheck | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/loadcheck b/plugins/loadcheck index 3fe3f72..b37ef45 100755 --- a/plugins/loadcheck +++ b/plugins/loadcheck @@ -10,7 +10,7 @@ Only takes email transactions if the system load is at or below a specified level. If this is running on a system that provides /kern/loadavg or -/proc/loadavg it will be used in stead of the 'uptime' command. +/proc/loadavg it will be used instead of the 'uptime' command. Once a load value is determined, it is cached for a period of time. See the cache_time below. @@ -46,7 +46,7 @@ Written by Peter Eisch . =cut -my $VERSION = 0.01; +my $VERSION = 0.02; sub register { my ($self, $qp, @args) = @_; From ab965b585c116dea564a10c594d17759da0ea876 Mon Sep 17 00:00:00 2001 From: Richard Siddall Date: Fri, 21 Mar 2014 09:48:49 -0400 Subject: [PATCH 4/5] Minor perldoc fix. --- plugins/loadcheck | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/loadcheck b/plugins/loadcheck index b37ef45..909b722 100755 --- a/plugins/loadcheck +++ b/plugins/loadcheck @@ -38,8 +38,6 @@ loadcheck cache_time 30 loadcheck max_load 7 uptime /usr/bin/uptime -=over 4 - =head1 AUTHOR Written by Peter Eisch . From aabefce3b9010e834c2a8e4ef9ec785f816e4f78 Mon Sep 17 00:00:00 2001 From: Richard Siddall Date: Fri, 21 Mar 2014 09:56:32 -0400 Subject: [PATCH 5/5] Added warning about expense of forking/exec to determine system load. Added SEE ALSO links to the postings containing the plugin and an alternate. --- plugins/loadcheck | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugins/loadcheck b/plugins/loadcheck index 909b722..44e424e 100755 --- a/plugins/loadcheck +++ b/plugins/loadcheck @@ -15,6 +15,8 @@ If this is running on a system that provides /kern/loadavg or Once a load value is determined, it is cached for a period of time. See the cache_time below. +Since fork/exec is expensive in perl you'll want to use cache_time to avoid increasing your load on every connection by checking system load. + =head1 CONFIG max_load @@ -38,6 +40,14 @@ loadcheck cache_time 30 loadcheck max_load 7 uptime /usr/bin/uptime +=head1 SEE ALSO + +Original version: http://www.nntp.perl.org/group/perl.qpsmtpd/2006/01/msg4422.html + +Variant with caching: http://www.nntp.perl.org/group/perl.qpsmtpd/2006/03/msg4710.html + +Steve Kemp's announcement of an alternate load limiter: http://www.nntp.perl.org/group/perl.qpsmtpd/2008/03/msg7814.html + =head1 AUTHOR Written by Peter Eisch .