Как сделать 25 запросов одновременно с HTTP :: Async в Perl?

Я делаю много HTTP-запросов и выбрал HTTP :: Async для этой работы. Я делаю более 1000 запросов и, если я просто сделаю следующее (см. Код ниже), у многих запросов истечет время до их обработки, потому что может пройти десятки минут, прежде чем обработка попадет к ним:

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

Поэтому я решил делать 25 запросов за раз, но я не могу придумать способ выразить это в коде.

Я попробовал следующее:

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
    }
}

Это, однако, не работает хорошо, потому что это слишком медленно в настоящее время. Теперь он ждет, пока все 25 запросов не будут обработаны, пока не добавит еще 25. Поэтому, если у него осталось 2 запроса, он ничего не делает. Я ожидаю обработки всех запросов на добавление следующей партии из 25.

Как я мог улучшить эту логику, чтобы сделать$async сделайте что-нибудь, пока я обрабатываю записи, но также убедитесь, что они не истекают.

Ответы на вопрос(2)

Решение Вопроса

Вы близки, вам просто нужно объединить два подхода! :-)

Не проверено, так что думайте об этом как о псевдокоде. В частности, я не уверен, еслиtotal_count это правильный способ использования, в документации не сказано. Вы также можете просто иметь$active_requests в противовес этому++ при добавлении запроса и-- когда вы получите ответ.

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);

}

Если вы не можете позвонитьwait_for_next_response достаточно быстро, потому что вы выполняете другой код, самое простое решение - сделать код прерывистым, переместив его в отдельный поток выполнения. Но если вы собираетесь начать использовать потоки, зачем использовать 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;
 27 окт. 2014 г., 13:55
Позволь намcontinue this discussion in chat.
 27 окт. 2014 г., 11:42
извините, stackoverflow форматирует мою ссылку. ссылка: http: // www. Интернет de - & gt; удалить пробел
 27 окт. 2014 г., 11:43
но я могу использовать любые другие URL и получаю ту же ошибку. E-G http: // Google. ком
 27 окт. 2014 г., 13:52
Успешно обновленный URI-1.64 (обновленный с 1.60) Я тестирую проблему на Fedora (x86_64 GNU / Linux) perl 5.16 и ubuntu (i686 athlon i386 GNU / Linux) perl 5.14. возможно я собираюсь опубликовать вопрос по этой ошибке
 27 окт. 2014 г., 10:41
Здравствуйте, ikegami, я пытаюсь запустить пример кода, но, к сожалению, я получаю следующее сообщение: 400 Не могу найти метод объекта quot; схема & quot; через пакет & quot; URI :: http - это проблема с URI, но я использую правильный URI & quot;web.de& Quot ;. Вы можете найти мой исходный код вsourcepod.com/pqyyxw07-51950, Спасибо

Ваш ответ на вопрос