Ich habe eine geplante Aufgabe, die regelmäßig (stündlich) ein Skript ausführt. Dieses Skript macht eine starke Interaktion mit der Datenbank und dem Dateisystem und benötigt regelmäßig einige Minuten zum Ausführen. Das Problem ist, dass die CPU-Auslastung des Servers während der Ausführung des Skripts ausbleibt und den normalen Betrieb verlangsamt. Gibt es eine Möglichkeit, diesen Prozess zu drosseln, so dass es länger dauert, aber nicht so viele Ressourcen verbraucht?
Ich habe verschiedene Konfigurationsoptionen für PHP angeschaut, aber es scheint keine zu geben, die meinen Anforderungen entsprechen.
Wenn memory_limit in php.ini auf etwas niedriger gesetzt wird, können meine Datenobjekte ziemlich schnell überlaufen.
Ich habe ähnliche Posts gesehen, wo Leute an bestimmten Stellen im Skript sleep () vorgeschlagen haben, aber das hindert das Skript nicht daran, den Server zu spicken.
Die optimale Lösung wäre eine Möglichkeit, dem Lamp-Stack (in diesem Fall Wamp) zu sagen, dass er nur 10% maximale CPU-Auslastung verwenden soll. Ich interessiere mich nicht für die Laufzeit und würde es vorziehen, dass es länger dauert, wenn es bedeutet, CPU-Zyklen pro Sekunde zu sparen. Meine alternative Lösung wäre, einen anderen Server mit Datenbankreplikation einzurichten, damit der Cron in die Stadt gehen kann, ohne alles andere zu verlangsamen.
Umgebung: Windows Server 2k3, Apache 2.2.11, PHP 5.2.9, MySQL 5.1
Ich schätze jede Einsicht in diese Situation.
BEARBEITEN: Ich schätze alle Antworten, auch die, die * nix-spezifisch sind. Es ist immer noch früh genug in meiner Situation, um die Hosting-Umgebung zu ändern. Hoffentlich hilft diese Frage anderen unabhängig vom Betriebssystem.
Das ist ein kniffliges Problem. Wenn Sie das PHP-Skript über die Befehlszeile ausführen, können Sie die Planungspriorität des Prozesses auf niedrig setzen ( start /low php.exe myscript.php
Ich glaube). Wenn Ihr PHP-Skript selbst die meiste Verarbeitung ausführt, die Ihre CPU verbraucht, könnte das funktionieren. Sie haben jedoch gesagt, dass Sie eine schwere Datenbank- und Dateisysteminteraktion durchführen, was diese Lösung nicht unterstützt. Es sieht so aus, als ob es einen MySQL-Hinweis "LOW_PRIORITY" für INSERT- und UPDATE-Abfragen gibt, der Ihnen dort helfen kann, aber ich habe diese nicht ausprobiert.
Sie können festlegen, dass Prozesse in Windows eine niedrigere Priorität haben. Ich bin mir nicht sicher, wie der Prozess gestartet wird. Wenn Sie jedoch festlegen, dass der Prozess eine niedrige Priorität hat, werden alle CPU-Ressourcen, die sie benötigen, mit einer niedrigen Priorität versehen.
In UNIX (LAMP) konnte ich das Problem lösen, indem ich die Belastung des Servers überprüfe, bevor ich die Schleife fortsetze
%Vor%Diese Funktion sollte auch unter Windows funktionieren, kann aber nicht garantiert werden. Unter Linux gibt es ein Array mit der Last der letzten 1 Minute, 5 Minuten und 15 Minuten
zurückÜberlegen Sie auch, ob Sie Ihre Skripts (wenn mit CLI) mit einer niedrigeren Priorität starten möchten (in Linux verwenden Sie "nett")
Sie können auch andere Werte verwenden, bevor Sie die Schleife fortsetzen, wie die Anzahl der aktiven Apache-Prozesse (Sie können die Seite 127.0.0.1/server_status?auto analysieren, wenn Sie den mod_status in httpd.conf aktiviert haben) oder auch die MySQL-Situation (aktive Verbindungen?)
Kannst du deinen Cron-Eintrag ändern, um dein Skript mit nett zu starten?
Es ist keine gute Idee , einen Server zum Bereitstellen von Clients und zum Analysieren von Daten zu verwenden.
Wenn Sie also nach einer endgültigen Lösung suchen, machen Sie ein paar Redesign Ihrer Anwendung und entlasten Sie die Datenanalyse von den Frontends und der Live-Datenbank auf ein anderes System, das dieser Aufgabe gewidmet ist.
Selbst wenn Sie den Analysator erfolgreich drosseln könnten, würde er wertvolle Ressourcen verbrauchen, die sonst den Benutzern zur Verfügung stehen würden.
Dies könnte eine schwierige Änderung sein, aber es könnte sich lohnen, Ihre Datenstrukturen in Iteratoren umzuwandeln. Wenn Sie in Ihrem Code auch Zirkelverweise haben, stellen Sie eine Methode wie clearReferences () zur Verfügung, die diese Objekte auflöst. Dies ist ein Problem, das übrigens in PHP 5.3 gelöst ist.
Also wenn du:
%Vor%Fügen Sie der Zeilenklasse eine Methode clearReferences () hinzu:
%Vor%Das ist alles, was ich mir im Moment vorstellen kann.
Ich habe eine Reihe von Skripten, die ich von cron in ähnlicher Weise mit nice ausführen:
0 * * * * nice -n19 php myscript.php
Dies wird die RAM-Nutzung nicht unterstützen (nur die Schreibweise des Skripts kann dies ändern), aber es verwendet nur die CPU, die sonst inaktiv wäre.
BEARBEITEN: Ich habe nicht bemerkt, dass die Frage eine Windows-Umgebung beinhaltete, sorry ... das hier für alle * nix-Benutzer mit dem gleichen Problem lassen.
Vielleicht versucht Ihr Skript einfach zu viel auf einmal. Würde es weniger tun, wenn es dreimal pro Stunde lief?
Eine andere Lösung könnte darin bestehen, einen zusätzlichen Server nur für die Ausführung dieser Art von "Backend" -Verarbeitung einzurichten. Dies wäre besonders effektiv, wenn es keine übermäßige Belastung in der Datenbank, nur den Webserver.
Ein weiterer Ansatz ist, ob die Arbeit in eine andere Richtung unterteilt werden kann. Diese Arten von Skripten haben oft einige große SQL-Anweisungen, die Ergebnisse generieren, die zum Generieren vieler kleiner SQL-Anweisungen verwendet werden. Wenn letzteres irgendwo abgelegt werden kann, können sie als ein späterer Schritt gegen die Datenbank ausgeführt werden. Bei einem solchen Ansatz können Sie auch eine ungepufferte Abfrage verwenden, um die Vorverarbeitungsdaten abzurufen, die den Speicherverbrauch durch den PHP-Code erheblich verringern könnten.
Wenn Sie Apache als Dienst ausführen, können Sie die Priorität ändern Einstellungen in der Win-Control-Center / Dienste. Ihre CPU-Auslastung wird trotzdem steigen, aber andere Programme werden bevorzugt vom Scheduler. Versuchen Sie auch, die Datenbank / den Server auf eine andere Festplatte als Ihre zu stellen Anwendungen.