AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

PHP: Skript parallel starten

Ein Thema von implementation · begonnen am 2. Jul 2011 · letzter Beitrag vom 2. Jul 2011
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von implementation
implementation

Registriert seit: 5. Mai 2008
940 Beiträge
 
FreePascal / Lazarus
 
#1

PHP: Skript parallel starten

  Alt 2. Jul 2011, 08:34
Hallo liebes Stammforum,

angenommen ich habe ein PHP-Skript A, dass vom Client angefordert wird.
Dieses soll jetzt im Hintergrund auf dem Server ein weiteres Skript B starten,
das nur an der Datenbank rumwerkelt.
Also etwa so:

-> A wird ausgeführt
-> A startet B
-> A liefert Ergebnis an Client zurück
-> B läuft im Hintergrund weiter
...
-> C wird ausgeführt
-> C beendet B
-> C liefert XML/JSON an Client zurück

Wie könnte ich das lösen?
Das beenden wäre ja nicht einmal das Problem, C könnte ja einen DB-Eintrag setzen, bei dem B sich selbst beendet.
Aber wie starte ich es?
  Mit Zitat antworten Zitat
Benutzerbild von alcaeus
alcaeus

Registriert seit: 11. Aug 2003
Ort: Dietersheim b. München
6.536 Beiträge
 
#2

AW: PHP: Skript parallel starten

  Alt 2. Jul 2011, 09:39
Moin,

um asynchrone Jobs zu starten gibt es mehrere Extensions. Ich bevorzuge hier Gearman, aus ganz einfachen Gruenden:
  • Die Client-Libraries, mit denen Jobs gestartet werden, gibt es fuer viele Programmiersprachen
  • Es ist kein Problem, ueber ein PHP-Script einen Job zu starten, der aber in C, Java oder Python geschrieben ist. Du kannst fuer jeden Teil der Anwendung die beste Sprache auswaehlen.
  • Die Datenuebertragung funktioniert anhand von Strings (genauer gesagt ein String-Parameter, ein String-Return), d.h. du entscheidest selbst wie du die Daten uebertragen willst (z.B. JSON-encodiert)
  • Es gibt eine telnet-Konsole, ueber die du den Status des Gearman ueberwachen kannst

Nachteil ist natuerlich, dass du einerseits ein apt-Paket fuer den Gearman-Server installieren musst sowie eine PECL-Extension (gearman) installieren musst damit alles laeuft. Hier ein Kurzueberblick wie das funktioniert.

Dein Script B, welches asynchron im Hintergrund laeuft, wird als Gearman-Skript registriert. Beim Start meldet es sich bei einem Gearman-Server an und registriert eine oder mehrere Funktionen und hinterlegt dazu eine Callback-Funktion, die dann tatsaechlich ausgefuehrt wird. Anschliessend tritt es in einen busy-waiting-Status und wartet auf Jobs.

Dein Script A sieht dass ein Hintegrundskript ausgefuehrt werden muss und baut ebenfalls eine Verbindung zum Gearman-Server auf. Anschliessend teilst du dem Gearman-Server mit, welche Funktion du ausfuehren willst und gibst ihm noch einen String-Parameter dazu. Du kannst auch entscheiden, ob du das Skript synchron oder asynchron starten willst. Bei der synchronen Ausfuehrung erhaelst du als Rueckgabewert das Ergebnis der in Script B ausgefuehrten Funktion (auch hier wieder nur ein String). Bie der asynchronen Ausfuehrung erhaelst du ein Token als Rueckgabewert, mit dem du den Status des Jobs pruefen kannst.

Damit Script C das Ergebnis am Ende irgendwo abholen kann, muss es einerseits das Token wissen, Script B muss das Ergebnis aber auch irgendwohin schreiben. Der Gearman-Server "vergisst" das naemlich, sobald Script B durch ist. Alternativ koenntest du auch mit Gearman-Tasks arbeiten, damit habe ich aber noch nicht viel gemacht.

Angenommen du hast nun die Scripte geschrieben und stellst fest dass die Ausfuehrung von Script B ueber Gearman lang dauert, weil viele Jobs in der Queue sind. Jede Instanz eines Gearman-Worker kann immer nur einen Job abarbeiten. Erst sobald dieser abgearbeitet ist, kommt der naechste dran. Du kannst aber soviele Instanzen starten wie du willst. Dann geschieht die Ausfuehrung von mehreren Tasks parallel.
Nun waechst die Anwendung weiter und du stellst fest dass der Server auf dem die Gearman-Jobs laufen komplett ausgelastet ist. Du kannst auch hier weiterskalieren und einfach auf einem zweiten Server dasselbe Script x-mal starten und wieder beim selben Gearman-Server registrieren. Dann verteilt der Gearman-Server die Jobs auch auf die beiden Maschinen.
Dieser Gearman-Server benoetigt normalerweise nicht viele Resourcen, aber es kann trotzdem sein dass er ueberlastet ist. Du kannst auch mehrere Instanzen eines Gearman-Servers aufsetzen. Wenn sich die Jobs alle bei allen Servern registrieren und die Clients in Script A sich auch bei allen Servern registrieren wird auch der Management-Teil skaliert. Du kannst diese Loesung also komplett in alle Richtungen skalieren, je nachdem wie du es brauchst.

So, ich hoff dass das halbwegs verstaendlich ist. Die PHP-Doku zur Gearman-Extension gibt dir einen guten Ueberblick ueber die Funktionen sowie ein paar Beispiele, anhand denen du das erstmal testen kannst. Auch die Gearman-Seite selbst stellt ein paar PHP-Beispiele zur Verfuegung.

Greetz
alcaeus
Andreas B.
Die Mutter der Dummen ist immer schwanger.
Ein Portal für Informatik-Studenten: www.infler.de
  Mit Zitat antworten Zitat
Benutzerbild von implementation
implementation

Registriert seit: 5. Mai 2008
940 Beiträge
 
FreePascal / Lazarus
 
#3

AW: PHP: Skript parallel starten

  Alt 2. Jul 2011, 10:15
Hmm, danke für deine ausführliche Antwort.
Leider hab ich auf den Server bloß nichts anderes als einen FTP-Zugang, Datenbank-Zugänge und PHP-Ausführungsrechte. Mit apt ist da nix
Ich gehe mal davon aus, dass auf dem Freehoster kein Gearman installiert ist.
Dann sieht es wohl so aus, als müsst ich das anders lösen. Schade.
Aber nochmals Vielen Dank!
  Mit Zitat antworten Zitat
Benutzerbild von alcaeus
alcaeus

Registriert seit: 11. Aug 2003
Ort: Dietersheim b. München
6.536 Beiträge
 
#4

AW: PHP: Skript parallel starten

  Alt 2. Jul 2011, 10:25
Leider hab ich auf den Server bloß nichts anderes als einen FTP-Zugang, Datenbank-Zugänge und PHP-Ausführungsrechte. Mit apt ist da nix
Du kannst mal gucken ob du die proc_*-Funktionen oder exec() usw. aufrufen kannst. Damit kannst du ebenfalls ein CLI-Script in den Hintergrund schieben. Wenn das nicht geht hast du es richtig schwer.

Greetz
alcaeus
Andreas B.
Die Mutter der Dummen ist immer schwanger.
Ein Portal für Informatik-Studenten: www.infler.de
  Mit Zitat antworten Zitat
Benutzerbild von implementation
implementation

Registriert seit: 5. Mai 2008
940 Beiträge
 
FreePascal / Lazarus
 
#5

AW: PHP: Skript parallel starten

  Alt 2. Jul 2011, 10:36
Zitat von PHP:
exec() has been disabled for security reasons
Wird wohl nix. Dann muss ich mir 'nen Workaround ausdenken, wie ich meinen Wunsch anders lösen kann.
  Mit Zitat antworten Zitat
Benutzerbild von alcaeus
alcaeus

Registriert seit: 11. Aug 2003
Ort: Dietersheim b. München
6.536 Beiträge
 
#6

AW: PHP: Skript parallel starten

  Alt 2. Jul 2011, 11:10
Dann kannst du die absolut haesslichste Variante nehmen, die es nur irgendwie gibt:
Die Seite die den Background-Task starten muss registriert mit register_shutdown_function() eine Funktion, welche ausgefuehrt wird sobald die Ausfuehrung des Scripts beendet wird (weil Ende erreicht oder exit() aufgerufen wurde). Das kostet dich dann zwar einen Apache-Prozess, du hast aber soweit ich weiss noch saemtliche Resourcen wie z.B. DB-Connections usw. Falls die zu dem Zeitpunkt schon weg sind, bleibt dir nichts anderes uebrig als den Output mit flush() rauszuschicken und anschliessend die entsprechende Berechnung oder was auch immer zu machen. Das Ergebnis landet in der DB und das andere Script kann das Ergebnis abholen.

Greetz
alcaeus
Andreas B.
Die Mutter der Dummen ist immer schwanger.
Ein Portal für Informatik-Studenten: www.infler.de
  Mit Zitat antworten Zitat
blackfin
(Gast)

n/a Beiträge
 
#7

AW: PHP: Skript parallel starten

  Alt 2. Jul 2011, 11:47
Ginge das nicht auch über simples AJAX?
(über jQuery, prototype oder mootools)

A wird aufgerufen, startet via AJAX ein weiteres Script B.
B macht seine Aufgaben, beendet sich aber nicht, da es in eine Schleife geht, die eine php-Session-Variable auf existenz prüft. (warum ist es eigentlich nötig, dass sich B nicht beendet, wenn es fertig ist und das Ergebnis an A per AJAX zurückgibt oder in eine Datei schreibt, so wie es normalerweise der Fall ist?)
C wird aufgerufen, setzt die Session-Variable.
B beendet sich, sobald die Session-Variable von C gesetzt wurde und gibt JSON / XML über Ajax zurück.

Oder habe ich einen Denkfehler?

Geändert von blackfin ( 2. Jul 2011 um 11:50 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von implementation
implementation

Registriert seit: 5. Mai 2008
940 Beiträge
 
FreePascal / Lazarus
 
#8

AW: PHP: Skript parallel starten

  Alt 2. Jul 2011, 12:01
Du hast recht!
Danke, das dürfte ja tatsächlich gehen

Ich wollte sowieso sehr viel Ajax verwenden, da lässt sich das gut einbauen.

Request -> B starten
-> B fügt Datensatz in DB ein
Request -> D holt B's Datensätze und liefert sie zurück
Request -> E fügt Datensätze in DB ein
-> B liest E's Datensätze aus DB
-> B packt neue Datensätze rein
Request -> D holt B's Datensätze und liefert sie zurück
Request -> C setzt Beenden-Befehl in die Datenbank
-> B beendet sich selbst

Geändert von implementation ( 2. Jul 2011 um 12:04 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von alcaeus
alcaeus

Registriert seit: 11. Aug 2003
Ort: Dietersheim b. München
6.536 Beiträge
 
#9

AW: PHP: Skript parallel starten

  Alt 2. Jul 2011, 12:52
B beendet sich, sobald die Session-Variable von C gesetzt wurde und gibt JSON / XML über Ajax zurück.
Da hast du das Problem dass der Browser bis dahin moeglicherweise schon nen Timeout gekriegt hat (z.B. gibt nginx nach 300 Sekunden nen 504 Gateway Timeout zurueck) oder ihn angenommen hat nachdem noch keine Daten gesendet wurden.
Ausserdem, was passiert wenn sich der Status der Applikation aendert, weil z.B. der Benutzer klug genug war, nen Refresh zu machen? Das Ergebnis vom Call an B laeuft dann ins Leere.

Greetz
alcaeus
Andreas B.
Die Mutter der Dummen ist immer schwanger.
Ein Portal für Informatik-Studenten: www.infler.de
  Mit Zitat antworten Zitat
Benutzerbild von implementation
implementation

Registriert seit: 5. Mai 2008
940 Beiträge
 
FreePascal / Lazarus
 
#10

AW: PHP: Skript parallel starten

  Alt 2. Jul 2011, 13:58
Der AJAX-Request soll ja asynchron sein, der User kriegt also gar nicht mit, dass da im Hintergrund 'nen Skript gestartet wurde. Wieso sollte er dann Refreshen?
Timeouts kann ich ja ignorieren, oder? Es geht mir ja nicht darum, dass B irgendetwas zurückliefert.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:32 Uhr.
Powered by vBulletin® Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2019 by Daniel R. Wolf