こんにちは! tomyhero です!
一つのリクエスト内で、複数のAPIを叩いたり、フィードを読み込んだりすると重くなって行きますよね! たとえば、複数のアフィリエイト広告APIを叩くときとか!
そういうときは、HTTP::Async を使うと良いと思います!
リクエストの結果を待たないで、次のリクエストを投げてくれます!で、後で回収をおこなうことができます。
サンプルコード
#!/usr/bin/perl
use HTTP::Async;
use HTTP::Request;
use LWP::UserAgent;
use Data::Dumper;
use Perl6::Say;
use Time::HiRes qw/gettimeofday tv_interval/ ;
# 適当なurl.本来なら別ドメインのサイトが良いと思う。攻撃ぽくなるので。
our @urls = (
'http://clip.livedoor.com/rss/recent',
'http://clip.livedoor.com/rss/hot',
'http://clip.livedoor.com/rss/popular',
);
&normal();
&async();
sub async {
my $t0 = [gettimeofday];
my $async = HTTP::Async->new;
for my $url (@urls) {
$async->add( HTTP::Request->new( GET => $url ) );
}
my @results = ();
while ( my ( $response, $id ) = $async->wait_for_next_response ) {
push @results, +{ id => $id, content => $response->content };
}
@results = sort { $a->{"id"} cmp $b->{"id"} } @results;
my $elapsed = tv_interval ( $t0, [gettimeofday]);
say 'async :' . $elapsed;
#warn Dumper \@results;
}
sub normal {
my $t0 = [gettimeofday];
my @results = ();
for my $url (@urls) {
my $ua = LWP::UserAgent->new;
my $response = $ua->get('http://search.cpan.org/');
push @results , $response->content;
}
my $elapsed = tv_interval ( $t0, [gettimeofday]);
say 'normal:' . $elapsed;
# warn Dumper \@results;
}
結果
ネットワークをかいしてるので、正確ではないですが、目安にはなります。
normal:1.315056 async :0.368374
add_with_opts() モジュールを使うと、proxyや、timeoutの設定ができたりしますよ。
最後に
早いサイトって良いですよね!
試してませんが、ParallelUserAgentもいいのかも! 場合によってはforkでもいいのかも!
:wq!



Leave a comment