2012-06-23 10 views
5

Sto facendo un sacco di richieste HTTP e ho scelto HTTP :: Async per fare il lavoro. Ho più di 1000 richieste da fare, e se faccio semplicemente quanto segue (vedi codice sotto), un sacco di richieste scadono nel momento in cui vengono elaborate perché possono impiegare decine di minuti prima che l'elaborazione arrivi a loro:Come posso fare 25 richieste alla volta con HTTP :: Async in Perl?

for my $url (@urls) { 
    $async->add(HTTP::Request->new(GET => $url)); 
} 
while (my $resp = $async->wait_for_next_response) { 
    # use $resp 
} 

Così ho deciso di fare 25 richieste per volta, ma non riesco a pensare a un modo per esprimerlo in codice.

ho provato la seguente:

while (1) { 
    L25: 
    for (1..25) { 
     my $url = shift @urls; 
     if (!defined($url)) { 
      last L25; 
     } 
     $async->add(HTTP::Request->new(GET => $url)); 
    } 
    while (my $resp = $async->wait_for_next_response) { 
     # use $resp 
    } 
} 

Questo però non funzionare bene come perché è troppo lento ora. Ora attende che tutte e 25 le richieste siano state elaborate fino a quando ne aggiunge altre 25. Quindi, se rimangono 2 richieste, non fa nulla. Devo aspettare che tutte le richieste siano elaborate per aggiungere il prossimo lotto di 25.

Come potrei migliorare questa logica per fare $async qualcosa mentre elaboro i record, ma anche assicurarmi che non scadano.

risposta

1

Sei vicino, hai solo bisogno di combinare i due approcci! :-)

Non testato, quindi pensarlo come uno pseudo codice. In particolare, non sono sicuro che il total_count sia il metodo giusto da usare, la documentazione non dice. Potresti anche avere un contatore $active_requests da te ++ quando aggiungi una richiesta e -- quando ricevi una risposta.

while (1) { 

    # if there aren't already 25 requests "active", then add more 
    while (@urls and $async->total_count < 25) { 
     my $url = shift @urls; 
     $async->add(...); 
    } 

    # deal with any finished requests right away, we wait for a 
    # second just so we don't spin in the main loop too fast. 
    while (my $response = $async->wait_for_next_response(1)) { 
     # use $response 
    } 

    # finish the main loop when there's no more work 
    last unless ($async->total_count or @urls); 

} 
2

Se non è possibile chiamare lo wait_for_next_response abbastanza velocemente perché si sta eseguendo un altro codice, la soluzione più semplice è rendere il codice interrompibile spostandolo in un thread di esecuzione separato. Ma se hai intenzione di iniziare a usare i thread, perché usare HTTP :: Async?

use threads; 
use Thread::Queue::Any 1.03; 

use constant NUM_WORKERS => 25; 

my $req_q = Thread::Queue::Any->new(); 
my $res_q = Thread::Queue::Any->new(); 

my @workers; 
for (1..NUM_WORKERS) { 
    push @workers, async { 
     my $ua = LWP::UserAgent->new(); 
     while (my $req = $req_q->dequeue()) { 
     $res_q->enqueue($ua->request($req)); 
     } 
    };  
} 

for my $url (@urls) { 
    $req_q->enqueue(HTTP::Request->new(GET => $url)); 
} 

$req_q->enqueue(undef) for @workers; 

for ([email protected]) { 
    my $res = $res_q->dequeue(); 
    ... 
} 

$_->join() for @workers; 
+0

Ciao Ikegami, provo a fare funzionare voi il codice di esempio, ma purtroppo ho ricevuto un messaggio di follow: 400 non può individuare il metodo oggetto "schema" tramite pacchetto "URI :: http - questo è URI problema sheme ma io uso la URI destro "http://www.web.de" è possibile trovare il mio codice sorgente in http://www.sourcepod.com/pqyyxw07-51950. thx – ovntatar

+0

scusate, stackoverflow formattando il mio link.il link è: http: // www. web. de -> cancella lo spazio char – ovntatar

+0

ma comunque posso usare qualsiasi altro URL e ricevo lo stesso errore. eg http: // google. com – ovntatar

Problemi correlati