我正在处理以下问题。
我们有一个程序可以自动将配置推送到多个路由器。执行此操作的Perl程序使用Parallel::ForkManager
库来完成这些推送的并行化。
在该计划的早期,以下情况发生......
$p = new Parallel::ForkManager($multi);
创建分支的主循环如下...
foreach my $node (@files) {
# only if we're running in parallel
if (ref($p)) {
$p->start() and next;
}
# ship the file & path off to the main sub that does
# all the heavy lifting
do_push($node);
# only if we're running in parallel
if (ref($p)) {
$p->finish();
}
}
# only if we're running in parallel
if (ref($p)) {
$p->wait_all_children();
}
这里的do_push($node)
子例程太长了,但总之,它为节点建立了一个日志文件,然后通过ssh连接到路由器并推送配置。然后退出并完成日志记录。
从表面上看,一切似乎都在工作,进程分叉,结果如预期。
...然而
虽然创建了单独的进程,但路由器的连接和配置的推送并不是并行发生的。通过netstat -an
可以很容易地验证ssh连接只是按顺序发生,而不是并行发生。只有在一个连接关闭后,下一个路由器才会连接。简而言之,我一次只能获得一个ssh连接。
有没有人知道为什么会这样,或者在哪里继续解决这个问题?
[edit]
根据评论,这里是对子程序中发生的事情的总结。出于空间和安全原因,我无法将其全部放在这里。
子程序的开始如下......
sub do_push {
my($data) = @_;
my($path,$router) = @$data;
$|++; # hopefully speed things up
($DEBUG or ($v > 2)) && print STDERR "PROCESSING: $router ($path)\n";
接下来的过程是......
子程序结束如下......
# finished with this router...
# append our archive file
my $ts = tv_interval($t0, [gettimeofday()]);
(!$DEBUG && $archive) && print S "ROUTER: $router:$ts:$disposition\n";
($DEBUG or ($v > 2)) && print STDERR "ROUTER COMPLETE: $router -> $ts sec\n";
# unlock and close our files
(($DEBUG > 1) or ($v > 2)) && print STDERR "UNLOCK AND CLOSE: $archfile\n";
(($DEBUG > 1) or ($v > 2)) && print STDERR "UNLOCK AND CLOSE: $summary\n";
(!$DEBUG && $archive) && flock(F, LOCK_UN);
(!$DEBUG && $archive) && flock(S, LOCK_UN);
(!$DEBUG && $archive) && close(F);
(!$DEBUG && $archive) && close(S);
return;
}
如果在调试模式下运行,子例程中的第一个调试语句:"PROCESSING: $router ($path)\n"
仅在前一个路由器完全完成子例程之后打印。肯定是多个进程分叉,我已经验证。只是那个"东西"阻止进程运行直到上一个进程完成。我正在努力寻找那些"的东西"是。
感谢任何帮助。
答案 0 :(得分:0)
<强> [解决] 强>
我讨厌回答我自己的问题,但是我确实找到了阻止的原因......
原来,问题是文件访问问题。在do_push()
循环中,程序记录到两个文件。一个文件是记录文件本身的结果,这个文件对子进程是唯一的,没问题。然而,该计划也写了一个&#34;摘要&#34;文件。所有子流程都记录了该文件。
会发生的事情是第一个线程会打开文件,记录一些东西,连接到路由器并推出命令。一旦完成,它将关闭文件。当然其他线程会阻塞,等待访问&#34;摘要&#34;文件。
对于小型路由器推送,一切都发生得如此之快,以至于看起来这一切都是并行发生的。只有当我们不得不向每个路由器推出1000个线路时,才会发现这并不是并行进行的。