Sven Rautenberg: PHP:

Beitrag lesen

Moin!

Ich lasse mir im PHP Script schon mit ps aux ermitteln wieviele Scripte ich schon gestartet habe und warte zur Zeit nach 20 Scripten mit Sleep(10) bis es wieder weniger als 20 Scripte sind.

Wieviele Skriptaufrufe machst du aufgrund der XML-Datei wirklich?

Wie lange läuft eins dieser Unterskripte? (Kommandozeile: "time BEFEHL" sagts dir).

Wieviel RAM braucht es maximal? (http://php.net/manual/en/function.memory-get-peak-usage.php sagt's dir).

Willkürlich nach 20 Starts eine Pause von 10 Sekunden zu machen funktioniert ja nur, wenn nach diesen 10 Sekunden diese Skripte beendet sind.

Wenn die Laufzeit eines einzelnen Skripts hingegen 20 Sekunden beträgt, dann startest du parallel 60 Skripte. Nämlich die ersten 20, dann nach zehn Sekunden nochmal 20, und nach 20 Sekunden fangen die nächsten 20 an, während die allerersten 20 so gerade eben fertig werden.

Wenn jedes Skript 1 MB an RAM benötigt, würdest du also 60 MB gleichzeitig bereitstellen müssen. Mit 1 MB bist du aber extrem sparsam, vermuten wir doch einfach mal 8 oder 16 MB pro Skript - dann muss dein Server 480 MB oder ein knappes Gigabyte bereitstellen können - und zwar OHNE Swapping! Wenn der Server mit Swapping anfangen würde, hast du sofort verloren, weil sich die Laufzeit jedes Skripts, welches auf Swap-Memory warten muss, exponentiell verlängert. Damit schaukelt sich das System sofort auf, denn nach den 10 Sekunden Wartezeit enden die vorherigen Skripte nicht und geben den Speicher frei, es werden aber neue gestartet, die auch wieder Speicher brauchen.

Es hängt etwas davon ab, was genau du da eigentlich tun willst, aber vermutlich willst du eine Queue implementieren, und begrenzt parallel abarbeiten. Mit PHP pur kann man da nichts machen (mir ist zumindest nichts bekannt), aber ich würde zu Gearman raten. Gearman ist der Verwalter von abzuarbeitenden Aufgaben und sich dafür bereit meldenden Workern. PHP hat dafür auch Librarys, den Gearman-Server selbst musst du so installieren.

PHP-Skripte können sich dann als dauerhaft wartende Worker anmelden und auf Aufgaben warten - je nach Anzahl der Worker, die du startest, wird die Aufgabe entsprechend parallel abgearbeitet, es werden aber niemals mehr Worker, als du startest.

Und dein Hauptskript stellt einfach ohne Pause für jede Aufgabe einen Job bei Gearman ein, ggf. auch direkt mit den zugehörigen Daten, wenn das nicht zuviele sind. Es kann dann auf die Erledigung aller Jobs warten und dabei den Zwischenstand (eingestellte Jobs, erledigte Jobs, noch wartende Jobs) bzw. bei Bedarf und entsprechend programmiertem Worker auch dessen konkreten Fortschritt abfragen und anzeigen - oder du verzichtest darauf und startest einfach nur die Jobs und bist im Hauptskript direkt fertig.

Du kannst natürlich auch jede andere Queue nehmen, oder was selbst mit MySQL basteln und einen Cronjob drauf ansetzen. Eventuell funktioniert es sogar eine Zeit lang, wenn du durch manuelles Messen, ausrechnen und Sicherheitsmarge hinzufügen die Ausführungshäufigkeit deines jetzigen Systems reduzierst. Aber du bist bei jedem Skript direkt abhängig von der Individualität der jeweiligen Aufgabe, sprich: Wenn EIN Aufruf eines Skripts unerwartet viele Daten zur Bearbeitung in den Speicher tut, und deshalb Swapping einsetzt, reicht das schon aus, um das Gesamtsystem in den Abgrund zu reißen.

- Sven Rautenberg