【发布时间】:2013-04-19 09:24:28
【问题描述】:
背景:
在阅读如何对我的 perl 脚本进行多线程处理时,我阅读了(来自http://perldoc.perl.org/threads.html#BUGS-AND-LIMITATIONS)
在大多数系统上,频繁且持续地创建和销毁 线程可以导致内存占用的不断增长 Perl 解释器。虽然只需启动线程和 然后 ->join() 或 ->detach() 它们,对于长期存在的应用程序,它是 更好地维护一个线程池,并在工作中重用它们 需要,使用队列来通知线程待处理的工作。
我的脚本将长期存在;它是一个始终运行的 PKI LDAP 目录监控守护进程。如果企业监控解决方案因任何原因停止运行,它将生成警报。我的脚本将检查我是否可以访问另一个 PKI LDAP 目录,并验证两者上的吊销列表。
问题:我在 google 上可以找到的所有内容都显示传递变量(例如标量)到线程队列而不是子例程本身......我想我只是不理解如何正确实现线程队列与如何实现线程(没有队列)相比。
问题 1:如何“维护线程池”以避免 perl 解释器慢慢消耗越来越多的内存?
问题 2 strong>:(不相关,但我发布了这段代码)在主程序结束时是否有安全的睡眠量,这样我一分钟内启动线程的次数不会超过一次? 60 似乎很明显,但如果循环很快,或者可能由于处理时间或其他原因错过一分钟,是否会导致它运行多次?
提前致谢!
#!/usr/bin/perl
use feature ":5.10";
use warnings;
use strict;
use threads;
use Proc::Daemon;
#
### Global Variables
use constant false => 0;
use constant true => 1;
my $app = $0;
my $continue = true;
$SIG{TERM} = sub { $continue = false };
# Directory Server Agent (DSA) info
my @ListOfDSAs = (
{ name => "Myself (inbound)",
host => "ldap.myco.ca",
base => "ou=mydir,o=myco,c=ca",
},
{ name => "Company 2",
host => "ldap.comp2.ca",
base => "ou=their-dir,o=comp2,c=ca",
}
);
#
### Subroutines
sub checkConnections
{ # runs every 5 minutes
my (@DSAs, $logfile) = @_;
# Code to ldapsearch
threads->detach();
}
sub validateRevocationLists
{ # runs every hour on minute xx:55
my (@DSAs, $logfile) = @_;
# Code to validate CRLs haven't expired, etc
threads->detach();
}
#
### Main program
Proc::Daemon::Init;
while ($continue)
{
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
# Question 1: Queues??
if ($min % 5 == 0 || $min == 0)
{ threads->create(&checkConnections, @ListOfDSAs, "/var/connect.log"); }
if ($min % 55 == 0)
{ threads->create(&validateRevocationLists, @ListOfDSAs, "/var/RLs.log"); }
sleep 60; # Question 2: Safer/better way to prevent multiple threads being started for same check in one matching minute?
}
# TERM RECEIVED
exit 0;
__END__
【问题讨论】:
-
愚蠢的问题:为什么要使用线程?为什么不一次检查一个 DSA?
-
有效问题! a)服务器有很多核心,所以我想“为什么不使用它们?” b)我是个十足的极客,也想为未来的脚本学习正确的线程技术(我讨厌采取简单的方法,呵呵)。如果发现问题,子例程会将 SNMP 陷阱发送到集中监控服务器,因此我的主脚本并不真正关心返回值,所以这感觉像是要走的路。
-
我可以理解这些原因,但我认为在这种情况下你真的不应该增加线程的复杂性,除非有令人信服的理由使用它们。
-
$min % 55 == 0表示$min == 55(给定范围为$min) -
$min % 5 == 0 || $min == 0与$min % 5 == 0相同
标签: multithreading perl queue