Ich muss ein Skript schreiben, die einige URLs parallel erhalten und etwas Arbeit erledigen. In der Vergangenheit habe ich immer Parallel::ForkManager
für solche Dinge verwendet, aber jetzt wollte ich etwas Neues lernen und versuchen asynchrone Programmierung mit AnyEvent
(und AnyEvent::HTTP
oder AnyEvent::Curl::Multi
) ... aber ich habe Probleme, AnyEvent zu verstehen und ein Skript zu schreiben, das sollte:Verständnis async in Perl auf spezifisches Beispiel
- öffnen einer Datei (jede Zeile ist eine separate URL)
- (von nun parallel, aber mit einer Grenze für zB 10 gleichzeitige Zugriffe)
- Lesedatei Zeile für Zeile (ich möchte nicht laden ganze Datei in den Speicher - es könnte groß sein)
- eine HTTP-Anfrage machen f oder dass URL
- Leseantwort-
- Updates MySQL Datensatz entsprechend
- (nächste Datei Zeile)
Ich habe viele Handbücher lesen, Tutorials, aber es ist immer noch schwer für mich Unterschiede zwischen Sperrung und nicht zu verstehen -Blockierungscode. Ich habe ähnliches Skript bei http://perlmaven.com/fetching-several-web-pages-in-parallel-using-anyevent gefunden, wo Herrn Szabo die Grundlagen erklärt, aber ich kann immer noch nicht verstehen, wie so etwas implementieren:
...
open my $fh, "<", $file;
while (my $line = <$fh>)
{
# http request, read response, update MySQL
}
close $fh
...
... und eine Gleichzeitigkeit Grenze in diesem Fall hinzufügen.
Ich würde für Hilfe sehr dankbar;)
UPDATE
Nach Ikegami Rat, den ich Net::Curl::Multi
einen Versuch gab. Ich bin sehr zufrieden mit den Ergebnissen. Nach Jahren der Verwendung Parallel::ForkManager
nur für die gleichzeitige Erfassung von Tausenden von URLs scheint Net::Curl::Multi
genial zu sein. Hier ist mein Code mit while
Schleife auf Dateihandle. Es scheint zu funktionieren, wie es sollte, aber da ich zum ersten Mal so etwas schreibe, möchte ich erfahrenere Perl-Benutzer bitten, einen Blick darauf zu werfen und mir zu sagen, ob es ein paar potentielle Fehler gibt, etwas, das ich vermisste usw. wenn ich fragen darf: Da ich nicht ganz verstehe, wie die Parallelität von Net::Curl::Multi
funktioniert, bitte sagen Sie mir, ob ich irgendwelche Probleme mit MySQL UPDATE Befehl (über DBI
) innerhalb RESPONSE
Schleife erwarten sollte (neben höheren Serverlast offensichtlich - ich erwarte final Skript, um mit ungefähr 50 gleichzeitigen N::C::M
Arbeitern zu laufen, vielleicht mehr).
#!/usr/bin/perl
use Net::Curl::Easy qw(:constants);
use Net::Curl::Multi qw();
sub make_request {
my ($url) = @_;
my $easy = Net::Curl::Easy->new();
$easy->{url} = $url;
$easy->setopt(CURLOPT_URL, $url);
$easy->setopt(CURLOPT_HEADERDATA, \$easy->{head});
$easy->setopt(CURLOPT_FILE, \$easy->{body});
return $easy;
}
my $maxWorkers = 10;
my $multi = Net::Curl::Multi->new();
my $workers = 0;
my $i = 1;
open my $fh, "<", "urls.txt";
LINE: while (my $url = <$fh>)
{
chomp($url);
$url .= "?$i";
print "($i) $url\n";
my $easy = make_request($url);
$multi->add_handle($easy);
$workers++;
my $running = 0;
do {
my ($r, $w, $e) = $multi->fdset();
my $timeout = $multi->timeout();
select $r, $w, $e, $timeout/1000
if $timeout > 0;
$running = $multi->perform();
RESPONSE: while (my ($msg, $easy, $result) = $multi->info_read()) {
$multi->remove_handle($easy);
$workers--;
printf("%s getting %s\n", $easy->getinfo(CURLINFO_RESPONSE_CODE), $easy->{url});
}
# dont max CPU while waiting
select(undef, undef, undef, 0.01);
} while ($workers == $maxWorkers || (eof && $running));
$i++;
}
close $fh;
Ich bin nicht festgelegt ist eine Menge „Callback-Funktion bekommen ". Es scheint, dass es anzeigt, wenn es eine Domain im URL-Host gibt. Ich erhalte diesen Fehler nicht, wenn ich eine IP verwende. Auch wenn ich z. 'print 'hat es geschafft!"; 'wo der' # process $ easy' steht, wird der Seiteninhalt automatisch ausgedruckt. – alan
Behoben, dass der Inhalt in $ easy gespeichert und nicht gedruckt wird. Ich bekomme den Rückruffehler nicht, den Sie bekommen ??[Versuchen Sie es mit der Änderung. Es könnte verwandt sein] – ikegami
Danke für Hilfe. Leider bekomme ich immer noch "Rückruffunktion ist nicht eingestellt". Eigentlich 4 mal, dann Dein 'printf'. Ich weiß nicht, woher es kommt. – alan