【发布时间】:2012-11-18 08:51:34
【问题描述】:
我正在使用 perl 的 threads 模块和我正在开发的简单爬虫,因此我可以并行下载页面。有时,我会收到如下错误消息:
Thread 7 terminated abnormally: read timeout at /usr/lib64/perl5/threads.pm line 101.
Thread 15 terminated abnormally: Can't connect to burgundywinecompany.com:80 (connect: timeout) at /usr/lib64/perl5/threads.pm line 101.
Thread 19 terminated abnormally: write failed: Connection reset by peer at /usr/lib64/perl5/threads.pm line 101.
当我在没有线程的情况下线性运行脚本时,我不会遇到这些错误。这些错误几乎看起来像是来自LWP::UserAgent 模块,但它们似乎不应该导致线程异常退出。在使用 perl 的线程时,我必须采取一些额外的预防措施吗?谢谢!
更新:
我已经找到了这些异常终止的来源,而且似乎是每当我使用LWP::UserAgent 发出请求时。如果我删除下载网页的方法调用,那么错误就会停止。
示例脚本
下面的脚本会导致我所说的一个错误。最后一个 URL 将超时,导致应该只是 HTTP::Repsonse 对象的一部分,而不是导致线程异常终止:
#!/usr/bin/perl
use threads;
use Thread::Queue;
use LWP::UserAgent;
my $THREADS=10; # Number of threads
#(if you care about them)
my $workq = Thread::Queue->new(); # Work to do
my @stufftodo = qw(http://www.collectorsarmoury.com/ http://burgundywinecompany.com/ http://beetreeminiatures.com/);
$workq->enqueue(@stufftodo); # Queue up some work to do
$workq->enqueue("EXIT") for(1..$THREADS); # And tell them when
threads->create("Handle_Work") for(1..$THREADS); # Spawn our workers
$_->join for threads->list;
sub Handle_Work {
while(my $todo=$workq->dequeue()) {
last if $todo eq 'EXIT'; # All done
print "$todo\n";
my $ua = LWP::UserAgent->new;
my $RESP = $ua->get($todo);
}
threads->exit(0);
}
【问题讨论】:
-
您是否确保为每个线程获得所有内容的新实例?审核代码以确保在每个线程中没有共享任何内容,每个线程都需要初始化自己的 perl 对象,应该传入很少的内容(如仅 URL),并且不应访问共享的全局变量。我怀疑这个问题只是设计错误。
-
@DarrylMiles,我在上面发布了一个导致错误的示例脚本。我很确定此示例脚本中没有共享任何内容,但我仍然收到错误消息。
-
好的脚本至少我们可以看到你在做什么。你只有4个项目放在$workq中,但是你启动了10个线程,每个线程可以处理多个项目。第 4 个线程不太可能看到任何工作要做。目标站点是否由您拥有/管理?你怎么知道他们没有连接洪水控制?如果它们是连续的,则原始错误中的线程编号表示超过 10。也许将当前线程开始/停止和工作的总数添加到子程序中,还在所有输出中发出线程-> tid()。你也许你更好地看到问题。
标签: multithreading perl exit