[Rio-pm] Metodos de Download em Massa

Renato Santos renato.cron em gmail.com
Qua Maio 24 14:57:19 PDT 2017


Recomendo usar qualquer coisa menos forks para fazer downloads.

Forks são pesados, geram muitas trocas de contextos desnecessárias para
tarefas tão triviais como downloads em paralelo.


Se o yada ta complicado, ainda tem o https://metacpan.org/pod/HTTP::Async
que com o Future fica uma mão na roda

Algo como:

use Future;
use Future::Utils qw( try_repeat fmap1 );
use IO::Async::Loop;
use Net::Async::HTTP;

my $loop = IO::Async::Loop->new;
my $http = Net::Async::HTTP->new(  # serio, é assim q eu uso em produção,
com max_connections_per_host=400
    max_connections_per_host => 400,
    timeout                  => 10 * 60
);
$loop->add($http);

sub DO_SOMETHING {
    my ( $algum_content, $url, $algum_contexto_talvez ) = @_;

    my $what = $http->do_request(
        method       => 'GET PORT DELETE...',
        uri          => "$url",
        content_type => 'text/plain',
        headers      => [
            'Content-Type' => 'text/plain'
        ],
        content => ( join "\n", @$algum_content )
    );

    $what = try_repeat { $what } until => sub {
        eval { $_[0]->get->code == 200 };
    };

    return $what;
}
my @futures;
for my $url ( 1 ... 100 ) {
    my $future =
      DO_SOMETHING( [...], $url, $algum_contexto_talvez )->on_done(
        sub {
            my $res = shift;

            if ( $res->content =~ /401 Unauthorized/ ) {

                # trata como se fosse erro, por exemplo
            }
            else {
                # ...
            }

        }

      )->on_fail(
        sub {
            my $failure = shift;
            log_error "error: $failure";
        }
      );

    push @futures, $future;
}

my @results = Future->needs_all(@futures)->get;



2017-05-24 16:53 GMT-03:00 Felipe Leprevost <leprevostfv em gmail.com>:

> Apenas como curiosidade Aureliano, de onde você está tentando obter os
> arquivos ?
>
> On Wed, May 24, 2017 at 3:21 PM Felipe da Veiga Leprevost <
> felipe em leprevost.com.br> wrote:
>
>> Apenas como curiosidade Aureliano, de onde você está tentando obter os
>> arquivos ?
>>
>> On Wed, May 24, 2017 at 3:19 PM Aureliano Guedes <guedes_1000 em hotmail.com>
>> wrote:
>>
>>> Opa,
>>>
>>> Yada achei muito complicado pra pouca coisa que vou fazer. Mas to
>>> convencido a tentar.
>>>
>>> Breno, o truncado é por causa que estou fazendo varios downloads com o
>>> Parallel::ForkManager de um arquivo no formato texto, onde cada
>>> identificador é um dado do arquivo, como eu trabalho com milhoes desses
>>> identificadores e o servidor recomenda se limitar a 500 por requisição
>>> acaba que tenho que fazer varios downloads. So que to imprimindo tudo em
>>> STDOUT e redirecionando a saida pra um aarquivo estilo UNIX mesmo > , então
>>> tem varios processo tenetando escrever na tela ao mesmo tempo, eu pensei em
>>> fazer um lock mas acho q isso vai fazer demorar.
>>>
>>>
>>> Exatamente aqui é o problema, IPC::ShareTable ou algo assim deve
>>> resolver. Alguma sujestão de solução ?
>>>
>>>
>>> my $pm = new Parallel::ForkManager($req);
>>> while(my $id = <$IN>){
>>> $cnt++;
>>> chomp $id;
>>> if ($cnt == $split || $. == $nl){ #$split = 500;
>>> push @ids, $id;
>>> my @tmp = @ids;
>>> undef @ids;
>>> $cnt = 0;
>>> $pm->start and next; # do the fork
>>> my @resp = get_fasta(\@tmp, $db, $timeout);
>>> if ($resp[0]){
>>> $resp[1] =~ s/^\s*\n+//mg;
>>> print STDOUT $resp[1];
>>> }
>>> else{
>>> print STDERR "Status: $resp[2]\n$resp[3]\nDetails: $resp[1]\n";
>>> print STDERR join (" ", "Fail:", @tmp, "\n");
>>> }
>>> $pm->finish; #tihs is a fork, at the end (here) the memory will be
>>> released
>>> }
>>> else{
>>> push @ids, $id;
>>> }
>>> }
>>> $pm->wait_all_children;
>>>
>>>
>>> ------------------------------
>>> *From:* Rio-pm <rio-pm-bounces+guedes_1000=hotmail.com em pm.org> on
>>> behalf of breno <oainikusama em gmail.com>
>>> *Sent:* Wednesday, May 24, 2017 3:54:47 AM
>>> *To:* Perl Mongers Rio de Janeiro
>>> *Subject:* Re: [Rio-pm] Metodos de Download em Massa
>>>
>>>
>>> Oi Aureliano,
>>>
>>> se você está interessado em benchmarks, pode experimentar o LWP::Curl em
>>> vez do Furl, ou se tiver paciência pra ir direto ao metal, Net::Curl ou
>>> WWW::Curl.
>>>
>>> O que quer dizer com "truncado"? Se a conexão cai depois de X bytes
>>> baixados (e se vc consegue garantir que o arquivo parcial contém apenas
>>> dados válidos), vc pode baixar só o que falta e depois juntar os dois
>>> pedaços na mão. Por exemplo, se o arquivo parcial foi baixado em
>>> "parcial.tmp":
>>>
>>> ---------8<---------
>>> my $ua = Furl->new;
>>> my $res = $ua->get( 'http://exemplo.com/arquivo.tmp', Range => 'byes='
>>> . -s 'parcial.tmp' . '-');
>>> open my $ fh, '>>', 'parcial.tmp;
>>> print $fh, $res->content;
>>> close $fh;
>>> ---------8<---------
>>>
>>> (código não testado, estou no celular)
>>>
>>> Se o servidor suporta conteúdo parcial (ele responde o primeiro request
>>> com Accept-Ranges), isso deve baixar o resto do arquivo. Idealmente, em vez
>>> de sobrescever o arquivo parcial, vc junta o conteúdo dos dois em um
>>> terceiro arquivo.
>>>
>>> Finalmente, se quiser baixar vários pedaços do arquivo em paralelo, pode
>>> experimentar o HTTP::Range e o LWP::Parallel::UserAgent, ou se inspirar
>>> neles e implementar sua própria solução paralela com Furl ou LWP::Curl.
>>>
>>> []s
>>> -b
>>>
>>> On 23:26, Tue, 23 May 2017 Aureliano Guedes, <guedes_1000 em hotmail.com>
>>> wrote:
>>>
>>>> Ola Monges,
>>>>
>>>>
>>>> Gostaria de saber qual metodo vocês mais gostam para fazer downloads em
>>>> massa.
>>>>
>>>>
>>>> Eu usava muito LWP, recentemente comecei usar uma combinação de
>>>> Parallel::ForkManager e Furl, mas pra meu tipo de dado tem truncado parte
>>>> dos download. (vale uma dica pra lidar com dados truncados?)
>>>>
>>>> No meu caso, eu to fazendo download de mais me milhoes de sequencias,
>>>> pra isso eu sigo a regra do servidor e peço apenas 500 por vez e limito em
>>>> 10 fork.
>>>>
>>>> Tem outros metodos que posso usar mas acabo perdendo e muito a
>>>> eficiência. Por isso pretendo testar um benchmark em varias formas
>>>> diferentes.
>>>>
>>>> Bom, sei que existem ferramentas, BioPerl, etc...
>>>>
>>>> Abraços,
>>>> acpguedes
>>>> _______________________________________________
>>>> Rio-pm mailing list
>>>> Rio-pm em pm.org
>>>> http://mail.pm.org/mailman/listinfo/rio-pm
>>>
>>> _______________________________________________
>>> Rio-pm mailing list
>>> Rio-pm em pm.org
>>> http://mail.pm.org/mailman/listinfo/rio-pm
>>
>> --
>> Felipe da Veiga Leprevost, Ph.D.
>> www.leprevost.com.br
>> Proteome Bioinformatics Lab
>> University of Michigan
>>
> --
> Felipe da Veiga Leprevost, Ph.D.
> www.leprevost.com.br
> Proteome Bioinformatics Lab
> University of Michigan
>
> _______________________________________________
> Rio-pm mailing list
> Rio-pm em pm.org
> http://mail.pm.org/mailman/listinfo/rio-pm
>



-- 
YAGNI,
Renato CRON
http://www.renatocron.com/blog/
@renato_cron <http://twitter.com/#!/renato_cron>
-------------- Próxima Parte ----------
Um anexo em HTML foi limpo...
URL: <http://mail.pm.org/pipermail/rio-pm/attachments/20170524/7eaf56bd/attachment-0001.html>


Mais detalhes sobre a lista de discussão Rio-pm