[英]Perl - Using LWP in multithread program
這是我的代碼:
use LWP;
use threads;
use strict;
use warnings;
my @thrds;
for (1..100)
{
push @thrds, threads->create( 'doit' );
}
for (@thrds)
{
$_->join();
}
sub doit
{
LWP::UserAgent->new->get("http://dx.doi.org/10.1002/aoc.1067");
}
我正在使用Windows 7 x64和ActivePerl 5.20.2 x64,我也嘗試了StrawberryPerl。 我有很多錯誤:
線程...異常終止:無法通過... / URI.pm第81行的包“ URI”找到對象方法“ _uric_escape”
在操作符在(eval 10)第8行處“ croak'用法:$ io-> getlines()'”附近找到了字符串
(您需要預先聲明嘶啞聲嗎?)
如果我加
sleep 1;
之前
push @thrds, threads->create( 'doit' );
沒關系的
有什么問題?
我不確定為什么,但是在處理動態加載的模塊時似乎存在問題。 在創建線程之前解決該問題,然后顯式加載它們。 換句話說,添加以下內容:
use Carp qw( );
use URI qw( );
我認為這里的問題將是內存占用。 畢竟,您正在加載LWP
庫,然后將您的進程克隆100次。
與流行的看法相反,perl中的線程甚至都不是輕量級的。 它們不太適合這種使用模型-每個線程都是您的進程的“完整副本”,這只是……不是一個好的計划。
我的perl副本-ActivePerl 5.20.2-沒有出現相同的問題(我不認為-我實際上不是想要向您列出的網站發送垃圾郵件)。
我建議您改寫線程以使用Thread::Queue
和較低的並行度:
use strict;
use warnings;
use LWP;
use threads;
use Thread::Queue;
my $workers = 10;
my $work_q = Thread::Queue->new();
my $url = "http://localhost:80";
sub worker_thread {
while ( my $url = $work_q->dequeue ) {
LWP::UserAgent->new->get($url);
}
}
threads->create( \&worker_thread ) for 1 .. $workers;
for ( 1 .. 100 ) {
$work_q->enqueue($url);
}
$work_q->end;
foreach my $thread ( threads->list ) {
$thread->join();
}
否則,基於分叉的方法也可能會更好地工作:
use strict;
use warnings;
use Parallel::ForkManager;
use LWP;
my $manager = Parallel::ForkManager->new(10);
for ( 1 .. 100 ) {
$manager->start and next;
LWP::UserAgent->new->get("http://localhost:80");
$manager->finish;
}
$manager->wait_all_children;
編輯:
對您的樣本進行更多測試-在運行5.20.2的RHEL上,我確實得到了類似的運行時錯誤
它們有些不同,這確實意味着這里必須存在某種競賽條件。
這很奇怪,因為線程應該是獨立的,而不是。
特別是-我的內核炸彈由於內存耗盡而產生了“殺手”,這要歸功於幾GB的內存占用,這是不使用此方法的一個很好的理由。
我的用RHEL和Perl 5.20.2運行代碼的測試用例也偶爾會觸發問題。
我得到的是類似的錯誤-偶爾出現。 我看不到明顯的消息來源想法。 它可能很簡單,就像打開文件描述符太多或消耗的內存太多一樣。 這是相當大的內存負擔。
使用Mojolicious框架,這非常簡單。 Mojo::UserAgent
類經設計可在Mojo::IOLoop
模塊的幫助下異步工作,盡管同步事務可用,但它們是使用標准異步調用的特殊情況實現的
use strict;
use warnings;
use Mojo;
my $ua = Mojo::UserAgent->new( max_redirects => 5 );
my $n;
for ( 1 .. 100 ) {
$ua->get('http://dx.doi.org/10.1002/aoc.1067' => \&completed);
++$n;
}
Mojo::IOLoop->start;
sub completed {
my ($ua, $tx) = @_;
Mojo::IOLoop->stop unless --$n > 0;
}
快速基准測試得出以下結果
我知道這是一個老話題,但是就在昨天,我遇到了這個問題。 下面的信息可能對某人有用。 我在類似的代碼(並行http請求)中從LWP中得到了幾種錯誤,包括
我添加以下行后,問題似乎消失了:
use IO::File;
不要問我為什么,我不知道:)偶然發現了這個問題。 我正在使用Strawberry Perl 5.24.0。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.