Prozesse parallel aufteilen
am 02.01.2007 21:20:29 von WOLfgang Schricker
Hallo,
aktuell mache ich in zwei Skripts (vereinfachter, zusammengefasster
Ablauf siehe unten) verschiedene Sachen für einen stetig wachsenden
Pool an IP-Adressen:
#-----8<-----8<------
@ips = fromDatabase(); # per DBI
foreach my $ip ( @ips )
{
# Skript 1 würde hier Daten aus Telnet-Dialogen gewinnen
@data = fromNetwork($ip); # per Net::Telnet
# Skript 2 würde hier Daten per Systemkommandos abholen
@data = `command $ip`;
# parse data ...
toDatabase(@data); # per DBI
}
#-----8<-----8<------
Bei immer mehr IP-Adressen (denken wir mal an einige Tausend)
addieren sich nun die Abfrage-, Bearbeitungs- bzw. Timeout-Zeiten.
Da ich bisher kaum Erfahrungen mit z. B. 'fork' habe bitte ich um
ein paar Tipps zu meinen Überlegungen:
1. Soll ich genannte Skripts zu "Vater-Prozessen" machen und "Söhne"
per 'fork' abkoppeln die ihre Daten an den Vater liefern der diese
in die Datenbank legt? Wie kontrolliere ich dann variabel die Menge
der gleichzeitig aktiven Söhne?
2. Sollte ich die Skripts (bei wenig Änderung) von einem
Shell-Skript aufrufen und per übergebener Variable im Skript steuern
welchen Anteil der IP-Adressen zu bearbeiten ist?
Z. B. vier mal das Skript starten und das 1. bis 4. Viertel der
IP-Adressen abarbeiten:
#-----8<-----8<------
for VIERTEL in 1 2 3 4
do /path/to/script.pl $VIERTEL &
done
#-----8<-----8<------
Vielen Dank bereits jetzt für jeden Ratschlag.
--
Mit freundlichen Grüßen
*WOL* fgang *S* chricker
Re: Prozesse parallel aufteilen
am 04.01.2007 00:31:30 von Sven Gottwald
* Quoting WOLfgang Schricker :
> aktuell mache ich in zwei Skripts (vereinfachter, zusammengefasster
> Ablauf siehe unten) verschiedene Sachen für einen stetig wachsenden
> Pool an IP-Adressen:
>
> #-----8<-----8<------
> @ips = fromDatabase(); # per DBI
>
> foreach my $ip ( @ips )
> {
> # Skript 1 würde hier Daten aus Telnet-Dialogen gewinnen
> @data = fromNetwork($ip); # per Net::Telnet
>
> # Skript 2 würde hier Daten per Systemkommandos abholen
> @data = `command $ip`;
>
> # parse data ...
>
> toDatabase(@data); # per DBI
> }
> #-----8<-----8<------
Ich habe gerade zur privaten Verwendung ein kleines Skript
geschrieben, mit dem ich mehrere Newsgruppen gleichzeitig durchsuchen
kann. Dabei konnte ich etwas in Threading mit Perl reinschnuppern,
versuch doch mal sowas in der Art (untested):
,----
| use threads;
| use Thread::Queue;
|
| my $max_parallel_jobs = 10; # wieviele Threads?
|
| @ips = fromDatabase();
| my $ip_queue = new Thread::Queue;
| $ip_queue->enqueue(@ips); # Queue aufbauen
|
| for (my $i=0; $i<= $max_parallel_jobs; $i++){ # jetzt die gewünschte
| my $thread = threads->new(\&worker); # Zahl von Threads starten
| }
|
| foreach my $thr (threads->list) { # Warten auf die Threads
| if ($thr->tid && !threads::equal($thr, threads->self)) {
| $thr->join;
| }
| }
|
| sub worker { # die eigentliche Routine
| while ($ip_queue->pending > 0) {
| my $ip = $ip_queue->dequeue; # Selbstbedienung :-)
| @data = fromNetwork($ip);
| @data = `command $ip`;
| # parse data ...
| toDatabase(@data);
| }
| }
`----
Du kannst auch Semaphoren einsetzen um die Zahl der Threads unter
Kontrolle zu halten (damit konnte ich leider nicht arbeiten). Lies
doch mal . Der Artikel
bezieht sich zwar noch auf das alte Threading-Modell von Perl 5.0,
trotzdem haben mir insbesondere die Beispiele weiter geholfen.
Ansonsten gibt es noch .
HTH
--
The truth may be out there, but lies are inside your head.
-- Terry Pratchett
Re: Prozesse parallel aufteilen
am 04.01.2007 12:36:24 von Ingo Menger
WOLfgang Schricker schrieb:
> Hallo,
> aktuell mache ich in zwei Skripts (vereinfachter, zusammengefasster
> Ablauf siehe unten) verschiedene Sachen für einen stetig wachsenden
> Pool an IP-Adressen:
>
> #-----8<-----8<------
> @ips =3D fromDatabase(); # per DBI
>
> foreach my $ip ( @ips )
> {
> # Skript 1 würde hier Daten aus Telnet-Dialogen gewinnen
> @data =3D fromNetwork($ip); # per Net::Telnet
>
> # Skript 2 würde hier Daten per Systemkommandos abholen
> @data =3D `command $ip`;
>
> # parse data ...
>
> toDatabase(@data); # per DBI
> }
> #-----8<-----8<------
>
> Bei immer mehr IP-Adressen (denken wir mal an einige Tausend)
> addieren sich nun die Abfrage-, Bearbeitungs- bzw. Timeout-Zeiten.
>
> Da ich bisher kaum Erfahrungen mit z. B. 'fork' habe bitte ich um
> ein paar Tipps zu meinen Überlegungen:
>
> 1. Soll ich genannte Skripts zu "Vater-Prozessen" machen und "Söhne"
> per 'fork' abkoppeln die ihre Daten an den Vater liefern der diese
> in die Datenbank legt? Wie kontrolliere ich dann variabel die Menge
> der gleichzeitig aktiven Söhne?
"an den Vater liefern" wird u.U. gar nicht so einfach.
Ansonsten kannst Du mit wait bzw. waitpid jederzeit auf das Ende eines
Kindes warten.
> 2. Sollte ich die Skripts (bei wenig Änderung) von einem
> Shell-Skript aufrufen und per übergebener Variable im Skript steuern
> welchen Anteil der IP-Adressen zu bearbeiten ist?
Das wäre natürlich viel eleganter.
> Z. B. vier mal das Skript starten und das 1. bis 4. Viertel der
> IP-Adressen abarbeiten:
> #-----8<-----8<------
> for VIERTEL in 1 2 3 4
> do /path/to/script.pl $VIERTEL &
> done
> #-----8<-----8<------
Besser noch, Du überlegst Dir eine flexiblere Art und Weise der
Parametrisierung.
Simpel, aber maximal mächtig wäre die Übergabe einer WHERE-Klausel
oder Teilen davon.
Je nach Datenbank und deren Isolation Mode mußt Du dann nur noch
sicherstellen, daß es nicht zu Datenbanklocks kommt.