6

私は多くの 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
}

ということで、1回あたり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、レコードの処理中に何かを実行できるようにするにはどうすればよいでしょうか。また、レコードがタイムアウトしないようにすることもできます。

4

2 に答える 2

2

他のコードを実行しているために十分な速度で呼び出すことができない場合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 (1..@urls) {
   my $res = $res_q->dequeue();
   ...
}

$_->join() for @workers;
于 2012-06-23T21:33:40.763 に答える
2

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

}
于 2012-06-24T04:02:20.687 に答える