Was passiert, wenn ich zu viele Hintergrundjobs starte?


13

Ich muss einige Arbeiten an 700 Netzwerkgeräten mithilfe eines Expect-Skripts ausführen. Ich kann es der Reihe nach erledigen, aber bis jetzt beträgt die Laufzeit ungefähr 24 Stunden. Dies liegt hauptsächlich an der Zeit, die zum Herstellen einer Verbindung benötigt wird, und an der Verzögerung der Ausgabe dieser Geräte (alte). Ich kann zwei Verbindungen herstellen und sie problemlos parallel ausführen, aber wie weit kann ich das treiben?

Ich kann mir nicht vorstellen, dass ich alle 700 auf einmal schaffen könnte. Sicherlich gibt es eine Grenze für das Nein. von Telnet-Verbindungen kann meine VM verwalten.

Wenn ich versucht hätte, 700 davon in einer solchen Schleife zu starten:

for node in `ls ~/sagLogs/`; do  
    foo &  
done

Mit

  • CPU 12 CPUs x Intel® Xeon® CPU E5649 @ 2,53 GHz

  • Speicher 47,94 GB

Meine Frage ist:

  1. Konnten möglicherweise alle 700 Instanzen gleichzeitig ausgeführt werden?
  2. Wie weit könnte ich kommen, bis mein Server sein Limit erreicht?
  3. Wenn dieses Limit erreicht ist, wird es nur warten, bis die nächste Iteration beginnt, foooder wird die Box abstürzen?

Ich arbeite leider in einer Unternehmensproduktionsumgebung, daher kann ich nicht genau versuchen, herauszufinden, was passiert.


3
Ich hatte viel Glück mit parallelrund 50 gleichzeitigen Jobs. Es ist ein großartiges Medium zwischen Parallelität von 1 und 700. Die andere nette Sache ist, dass es keinen Stapel gibt. Eine einzelne unterbrochene Verbindung blockiert nur sich selbst, keine der anderen. Der Hauptnachteil ist das Fehlermanagement. Keiner dieser Shell-basierten Ansätze kann mit Fehlern umgehen. Sie müssen den Erfolg manuell überprüfen und Ihre eigenen Versuche unternehmen.
Adam

1
Ihre Aufgabenwarteschlange kann heute 700 sein, aber kann die Größe erweitert werden? Achten Sie darauf, dass der Swap-Bereich wächst. Dies bedeutet, dass Sie die Speichergrenze erreicht haben. Und CPU% ist kein gutes Maß (für Linux / Unix), besser ist es, den Lastdurchschnitt (Länge der Ausführungswarteschlange) zu berücksichtigen.
ChuckCottrill

1
Die letzte Möglichkeit, die ich bei meinem noch ein bisschen neuen Job durchbrach, bestand darin, versehentlich mehr als eine Million kurzlebiger Hintergrundjobs gleichzeitig auszuführen. Es handelte sich um JVMs (Warte, warte, lege die Mistgabeln ab), sodass die Konsequenzen auf Hunderttausende von Fehlerberichtsdateien beschränkt waren, mit denen Threads nicht gestartet werden konnten.
Michaelb958 - GoFundMonica


1
@KuboMD Und solange noch niemand Ihren Code verwenden möchte.
l0b0

Antworten:


17

Konnten möglicherweise alle 700 Instanzen gleichzeitig ausgeführt werden?

Das hängt davon ab, was Sie unter gleichzeitig verstehen. Wenn wir wählerisch sind, können sie es nicht, es sei denn, Sie haben 700 Ausführungsthreads auf Ihrem System, die Sie verwenden können (also wahrscheinlich nicht). Realistisch gesehen können sie dies jedoch wahrscheinlich, vorausgesetzt, Sie haben genügend RAM und / oder Swap-Speicherplatz auf dem System. UNIX und seine verschiedenen untergeordneten Betriebssysteme können erstaunlich gut mit enormen Nebenläufigkeiten umgehen. Dies ist einer der Gründe, warum sie für die Verwendung von HPC in großem Maßstab so beliebt sind.

Wie weit könnte ich kommen, bis mein Server sein Limit erreicht?

Dies ist ohne eine ganze Reihe weiterer Informationen nicht konkret zu beantworten. Ziemlich viel, müssen Sie genug Speicher haben, um zu erfüllen:

  • Der gesamte Laufzeitspeicherbedarf eines Jobs, mal 700.
  • Der Speicherbedarf von bash, um so viele Jobs zu verwalten (bash ist nicht schrecklich, aber die Jobsteuerung ist nicht gerade speichereffizient).
  • Alle anderen Speicheranforderungen auf dem System.

Angenommen, Sie treffen dies (auch hier müssen Sie sich mit nur 50 GB RAM noch mit anderen Problemen befassen:

  • Wie viel CPU-Zeit wird durch Bash-on-Job-Kontrolle verschwendet? Wahrscheinlich nicht viel, aber mit Hunderten von Arbeitsplätzen könnte es von Bedeutung sein.
  • Wie viel Netzwerkbandbreite wird dies benötigen? Das einfache Öffnen all dieser Verbindungen kann je nach Bandbreite und Latenz Ihr Netzwerk für einige Minuten überlasten.
  • An viele andere Dinge habe ich wahrscheinlich nicht gedacht.

Wenn diese Grenze erreicht ist, wartet es dann nur noch, bis die nächste Iteration beginnt, oder stürzt die Box ab?

Es kommt darauf an, welches Limit erreicht wird. Wenn es sich um Arbeitsspeicher handelt, stirbt auf dem System etwas ab (genauer gesagt, der Kernel versucht, Speicher freizugeben), oder das System selbst stürzt ab (es ist nicht ungewöhnlich, Systeme so zu konfigurieren, dass sie absichtlich abstürzen, wenn der Arbeitsspeicher knapp wird). Wenn es CPU-Zeit ist, wird es einfach ohne Probleme weitergehen, es wird einfach unmöglich sein, mehr auf dem System zu tun. Wenn es sich jedoch um das Netzwerk handelt, können andere Systeme oder Dienste abstürzen .


Was Sie hier wirklich brauchen, ist, nicht alle Jobs gleichzeitig auszuführen. Teilen Sie sie stattdessen in Stapel auf, und führen Sie alle Jobs innerhalb eines Stapels gleichzeitig aus, lassen Sie sie beenden und starten Sie dann den nächsten Stapel. GNU Parallel ( https://www.gnu.org/software/parallel/ ) kann dafür verwendet werden, ist jedoch in dieser Größenordnung in einer Produktionsumgebung weniger als ideal (wenn Sie damit einverstanden sind, werden Sie nicht zu aggressiv, Wie gesagt, Sie könnten das Netzwerk überfluten und Systeme beeinflussen, die Sie sonst nicht berühren würden. Ich würde wirklich empfehlen, sich ein geeignetes Netzwerk-Orchestrierungs-Tool wie Ansible ( https://www.ansible.com/) anzuschauen.), da dies nicht nur Ihre Nebenläufigkeitsprobleme löst (Ansible führt die Stapelverarbeitung wie oben erwähnt automatisch durch), sondern Ihnen auch viele andere nützliche Funktionen bietet, mit denen Sie arbeiten können (wie idempotente Ausführung von Aufgaben, nette Statusberichte und native Integration mit eine sehr große Anzahl anderer Werkzeuge).


Es gibt verschiedene Möglichkeiten, eine begrenzte Anzahl von Hintergrundaufgaben auszuführen (unter Verwendung von Bash, Perl, Python usw.), den Abschluss von Aufgaben zu überwachen und weitere Aufgaben auszuführen, wenn vorherige Aufgaben abgeschlossen sind. Ein einfacher Ansatz wäre, Stapel von Aufgaben zu sammeln, die durch Dateien in Unterverzeichnissen dargestellt werden, und jeweils einen Stapel zu verarbeiten. Es gibt andere Möglichkeiten ...
ChuckCottrill

Umfasst dies auch Unix-ähnliche Systeme? Und was ist "GUN parallel"?
Biswapriyo

2
@ChuckCottrill Ja, es gibt in der Tat andere Möglichkeiten, dies zu tun. Aufgrund meiner eigenen Erfahrung mit dieser Art von Dingen ist es jedoch fast immer besser, nur ein echtes Orchestrierungs-Tool zu erwerben, als eine eigene Lösung zu entwickeln, insbesondere, wenn Sie ein paar Dutzend Systeme in Bezug auf die Skalierung hinter sich haben.
Austin Hemmelgarn


3
@forest Ja, Sie können Rlimits verwenden, um ein Abstürzen des Systems zu verhindern. In einem solchen Fall ist es jedoch nicht einfach, diese zu korrigieren (Sie müssen im Voraus die Ressourcenanforderungen für die Aufgaben kennen) und schützen das System nicht Rest des Netzwerks vor möglichen Auswirkungen dieser Jobs (was wahrscheinlich ein viel größeres Problem ist als ein Absturz des lokalen Systems).
Austin Hemmelgarn

12

Es ist schwer zu sagen, wie viele Instanzen in der von Ihnen beschriebenen Weise als Hintergrundjobs ausgeführt werden könnten. Ein normaler Server kann jedoch 700 gleichzeitige Verbindungen aufrechterhalten, solange Sie dies korrekt ausführen. Webserver tun dies die ganze Zeit.

Darf ich vorschlagen, dass Sie GNU parallel ( https://www.gnu.org/software/parallel/ ) oder etwas Ähnliches verwenden, um dies zu erreichen? Es würde Ihnen eine Reihe von Vorteilen gegenüber dem Hintergrund des Arbeitsansatzes bringen:

  • Sie können die Anzahl der gleichzeitigen Sitzungen einfach ändern.
  • Und es wird warten, bis die Sitzungen abgeschlossen sind, bevor neue gestartet werden.
  • Es ist einfacher abzubrechen.

Hier finden Sie einen schnellen Einstieg: https://www.gnu.org/software/parallel/parallel_tutorial.html#A-single-input-source


1
Interessant! Ich werde mir das mal ansehen. Wissen Sie, ob der Versuch einer solchen Operation (ohne die Hilfe von Parallel) den Hypervisor zum Absturz bringen könnte?
KuboMD

2
@KuboMD Wenn Sie den Hypervisor mit etwas so Alltäglichem zum Absturz bringen können, dann ist das ein Fehler im Hypervisor :)
hobbs

Abgesehen davon verwenden Webserver häufig Threading oder ereignisbasierte Verarbeitung (Beispiel: gunicorn.org )
ChuckCottrill

10

Die Verwendung &für die parallele Verarbeitung ist in einigen Fällen in Ordnung und wenn Sie den Fortschritt überwachen. Wenn Sie jedoch in einer Unternehmensproduktionsumgebung arbeiten, benötigen Sie etwas, das Ihnen eine bessere Kontrolle bietet.

ls ~/sagLogs/ | parallel --delay 0.5 --memfree 1G -j0 --joblog my.log --retries 10 foo {}

Dies wird foofür jede Datei in ausgeführt ~/sagLogs. Es wird alle 0,5 Sekunden ein Job gestartet, es werden so viele Jobs wie möglich parallel ausgeführt, solange 1 GB RAM frei ist, aber die Grenzen Ihres Systems (z. B. Anzahl der Dateien und Prozesse) werden eingehalten. Dies bedeutet normalerweise, dass Sie 250 Jobs gleichzeitig ausführen, wenn Sie die Anzahl der zulässigen offenen Dateien nicht angepasst haben. Wenn Sie die Anzahl der geöffneten Dateien anpassen, sollten Sie kein Problem damit haben, 32000 parallel auszuführen - solange Sie über genügend Arbeitsspeicher verfügen.

Wenn ein Auftrag fehlschlägt (dh mit einem Fehlercode zurückgegeben wird), wird er zehnmal wiederholt.

my.log wird Ihnen mitteilen, ob ein Auftrag erfolgreich war (nach möglicherweise erneuten Versuchen) oder nicht.


Das sieht sehr vielversprechend aus, danke.
KuboMD

Ich habe einen einfachen Test gemacht cat ~/sagLogs/* >> ~/woah | parallelund der heilige Moly war schnell. 1.054.552 Zeilen im Handumdrehen.
KuboMD

3
Der Befehl, den Sie gegeben haben, hat eine doppelte Umleitung, daher glaube ich nicht, dass er das tut, was Sie beabsichtigen. GNU Parallel hat einen Overhead von 10 ms pro Job, sodass 1 Million Jobs in der Größenordnung von 3 Stunden dauern sollten.
Ole Tange

1
Es ist überhaupt nicht anwendbar, wenn Sie lediglich die Dateien verketten möchten.
Ole Tange

1
@KuboMD eine triviale CPU-Busy-Schleife, wie awk 'BEGIN{for(i=rand()*10000000; i<100000000;i++){}}' sie zum Herumspielen funktionieren würde. Oder probieren Sie es bei einer Aufgabe sleep 10aus, bei der nJobs im Flug bleiben, ohne viel CPU-Zeit zu verbrauchen. zB time parallel sleep ::: {100..1}um die Schlafzeiten von 100 auf 1 Sekunde zu senken.
Peter Cordes

1

Was passiert, wenn ich zu viele Hintergrundjobs starte?

Das System wird langsam und reagiert nicht mehr. Der schlimmste Fall ist, dass es nicht mehr reagiert. Drücken Sie einfach den Ein- / Ausschalter und führen Sie einen harten Neustart durch. Dies würde bedeuten, dass etwas als Root ausgeführt wird, auf dem es das Privileg hatte, damit durchzukommen. Wenn Ihr Bash-Skript unter normalen Benutzerberechtigungen ausgeführt wird, fällt Ihnen als Erstes Folgendes ein/etc/security/limits.conf und /etc/systemd/system.confund alle Variablen darin [ideal gesprochen] verhindern Benutzer (n) von Überlastung des Systems.

  • cpu = xeon E5649, das ist eine 12- Core- CPU; Sie können also 12 Kerne für 12 Prozesse gleichzeitig ausführen, wobei jeweils einer von zwölf Kernen zu 100% verwendet wird. Wenn Sie 24 Prozesse starten, wird jeder mit 50% Auslastung auf jedem der zwölf Kerne ausgeführt, 700 Prozesse = 1,7%. Es handelt sich jedoch um einen Computer, solange alles in einer angemessenen Zeit ordnungsgemäß abgeschlossen wird. Dann ist dies = Erfolg. effizient zu sein ist nicht immer relevant.

    1. Konnten möglicherweise alle 700 Instanzen gleichzeitig ausgeführt werden? Sicher ist 700 keine große Zahl; Mein /etc/security/limits.conf maxprocStandard ist zum Beispiel 4.135.275

    2. Wie weit könnte ich kommen, bis mein Server sein Limit erreicht? Weit über 700 bin ich mir sicher.

    3. Grenzen ... was passieren wird, wenn das Skript unter einem Benutzerkonto gestartet wird (und im Allgemeinen gilt root so limits.confziemlich für alle), ist, dass das Skript nur beendet wird, nachdem es foo &700-mal versucht hat; Sie würden erwarten, dass dann 700 foo- Prozesse mit jeweils einer anderen PID angezeigt werden, aber Sie sehen möglicherweise nur 456 (Auswahl der Zufallszahl) und die anderen 244 wurden nie gestartet, weil sie durch eine Sicherheits- oder Systembeschränkung blockiert wurden.

Million $ Frage: Wie viele sollten Sie gleichzeitig ausführen?

mit spot zusammenarbeiten, um die Dinge so schnell wie möglich zu erledigen ... den Overhead minimieren und die Effizienz steigern. Als 12 Kerne (oder 24, wenn Sie 2 CPUs haben) beginnen Sie mit 12 (oder 24) auf einmal und erhöhen dann diese gleichzeitige Chargennummer um 12 oder 24, bis Sie keine Laufzeitverbesserung mehr feststellen. Netzwerk befasst haben und gesagt haben, dass jeder eine Telnet-Verbindung herstellen wird, ist zu vermuten, dass Sie auf Netzwerklimits und Overhead stoßen, bevor Sie dies für CPU- und RAM-Limits tun. Aber ich weiß nicht, was Sie konkret tun. Was wahrscheinlich passieren wird, ist, dass Sie alle 700 gleichzeitig starten können, aber die Dinge werden automatisch blockiert, bis frühere Prozesse und Netzwerkverbindungen aufgrund verschiedener Systemgrenzen oder ähnlichem beendet und geschlossen sind Die ersten 500 starten, die restlichen 200 nicht, weil System- oder Kernel-Limits dies verhindern. Doch wie viele auf einmal rennen, es wird etwas Süßliches geben

tipp: google max telnet verbindungen und sehen, wie dies auf ihre systeme zutrifft. Vergessen Sie auch nicht über Firewalls. Berechnen Sie außerdem schnell den pro Prozess benötigten Arbeitsspeicher x 700. Stellen Sie sicher, dass <verfügbarer Arbeitsspeicher (in Ihrem Fall ca. 50 GB) vorhanden ist. Andernfalls verwendet das System SWAP und reagiert im Grunde nicht mehr. Wenn Sie also 12, 24, N Prozesse gleichzeitig ausführen und den freien RAM überwachen, erhöhen Sie N, wenn Sie bereits einige Kenntnisse darüber haben, was gerade passiert.

Standardmäßig begrenzt RHEL die Anzahl der Telnet-Verbindungen von einem einzelnen Host auf 10 gleichzeitige Sitzungen. Dies ist eine Sicherheitsfunktion ... auf 10 gesetzt, /etc/xinetd.conf, ändern Sie den Wert "per_source".

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.