Какой на данный момент самый удобный и надежный кроссплатформенный модуль Perl для параллельной загрузки? - PullRequest
3 голосов
/ 03 ноября 2010

Мне нужно будет загрузить несколько наборов данных, просто разместив ссылку на URL и получив XML взамен. Я смогу ускорить это, выполняя более одного запроса за раз, но вот ловушка:

Он должен работать как в Windows, так и в Linux, так что потоков и вилок оба отсутствуют . (Так как это чисто IO, я не думаю, что они тоже нужны.)

Кроме того, мои коллеги не очень хорошо понимают Perl, но должны быть в состоянии понять, как его использовать (не обязательно, что происходит, использование в порядке). Поэтому я был бы рад, если бы его API был несколько простым .

Прямо сейчас я смотрю на IO :: Lambda для этого.

Любые другие предложения?

После смерти: Основываясь на предложении Дрегтуна, я собрал это вместе, что отлично справляется с работой: https://gist.github.com/661386 Возможно, вы скоро увидите это на CPAN.

Ответы [ 3 ]

6 голосов
/ 03 ноября 2010

Посмотрите на AnyEvent::HTTP. Согласно матрице платформы CPAN он компилируется и работает в Windows.

Ниже приведен простой пример асинхронной POSTing (http_post).

use 5.012;
use warnings;
use AnyEvent::HTTP;

my $cv = AnyEvent->condvar;

my @urls = (
    [google => 'http://google.com', 'some body'],
    [yahoo  => 'http://yahoo.com' , 'any body' ],
);

for my $site (@urls) {
    my ($name, $url, $body) = @$site;
    $cv->begin; 
    http_post $url, $body => sub {
        my $xml = shift;
        do_something_with_this( $name, $xml );
        $cv->end;
    }
}

# wait till all finished
$cv->recv;
say "Finished";

sub do_something_with_this { say @_ }

NB. Запомните все, что вы решите сделать с помощью do_something_with_this, старайтесь избегать всего, что блокирует . Смотрите другие неблокирующие AnyEvent модули

/ I3az /

5 голосов
/ 03 ноября 2010

Вы можете попробовать использовать LWP :: Parallel .

Обновление:

Я только что попытался собрать его на Windows XP с ActiveState 5.10.1 и столкнулся с кучей тестовых сбоев, некоторые из которых связаны со скриптом TEST, слепо добавляющим .. ко всем записям в @INC, а другие, похоже из-за несоответствия версий LWP::Protocol::* классам.

Это беспокойство. Я мог бы пойти с Parallel :: ForkManager в сочетании с LWP .

#!/usr/bin/perl

use strict; use warnings;
use Config::Std { def_sep => '=' };
use File::Slurp;
use HTTP::Request::Common qw(POST);
use LWP::UserAgent;
use Parallel::ForkManager;

die "No config file specified\n" unless @ARGV;
my ($ini) = @ARGV;

read_config $ini, my %config;

my $pm = Parallel::ForkManager->new(10);

my @urls = @{ $config{''}{url} };

for my $url ( @urls ) {
    $pm->start and next;
    my $param = [ %{ $config{$url} } ];
    my $request = POST $url, $param;
    my $ua = LWP::UserAgent->new;
    my $fn = sprintf '%s-%s-%s.xml',
                     map $request->$_, qw( method uri content);
    $fn =~ s/\W+/_/g;
    my $response = $ua->request( $request );
    if ( $response->code == 200 ) {
        write_file $fn, \ $response->as_string;
    }
    else {
        warn $response->message, "\n";
    }
    $pm->finish;
}
$pm->wait_all_children;

Вот пример файла конфигурации:

url = http://one.example.com/search
url = http://two.example.com/query
url = http://three.example.com/question

[http://one.example.com/search]
keyword = Perl
limit = 20

[http://two.example.com/query]
type = Who is
limit = 10

[http://three.example.com/question]
use = Perl
result = profit

Обновление:

Если вам нужно убедить себя, что выполнение не является последовательным, попробуйте следующий короткий сценарий:

#!/usr/bin/perl

use strict; use warnings;

use Parallel::ForkManager;

my $pm = Parallel::ForkManager->new(2);

for my $sub (1 .. 4) {
    $pm->start and next;
    for my $i ('a' .. 'd') {
        sleep rand 3;
        print "[$sub]: $i\n";
    }
    $pm->finish;
}

$pm->wait_all_children;

Выход:

[1]: a
[1]: b
[2]: a
[1]: c
[1]: d
[2]: b
[3]: a
[3]: b
[3]: c
[2]: c
[3]: d
[2]: d
[4]: a
[4]: b
[4]: c
[4]: d

Что касается вашего комментария о "надежности", я считаю, что он ошибочен. То, что вы делаете, моделируется следующим скриптом:

#!/usr/bin/perl

use strict; use warnings;

use Parallel::ForkManager;
use YAML;

my @responses = parallel_run();

print Dump \@responses;

sub parallel_run {
    my $pm = Parallel::ForkManager->new(2);
    my @responses;
    for my $sub (1 .. 4) {
        $pm->start and next;
        for my $i ('a' .. 'd') {
            sleep rand 3;
            push @responses, "[$sub]: $i";
        }
        $pm->finish;
    }
    $pm->wait_all_children;
    return @responses;
}

Вывод, который вы получите от этого будет:

--- []

Вам решать, почему. Вот почему Parallel::ForkManager позволяет регистрировать обратные вызовы. Так же, как те, которые вы используете с AnyEvent::HTTP.

Какой модуль вы используете, это ваше собственное дело. Только не продолжайте делать явно ложные заявления.

1 голос
/ 03 ноября 2010

Mojo :: UserAgent также может выполнять асинхронную параллельную http. Его API-интерфейс может быть проще для людей, не относящихся к Perl, чем некоторые другие модули.

Не уверен, что он еще считается "надежным" ..

...