php.de

Zurück   php.de > Webentwicklung > PHP-Fortgeschrittene

PHP-Fortgeschrittene Arbeiten mit PHP ohne Einschränkungen

Antwort
 
LinkBack Themen-Optionen Thema bewerten
Alt 25.09.2004, 15:28  
Gast
 
Beiträge: n/a
Standard Skript mit langer Ausführungszeit => mehrfach ausgeführt

Extremes Problem auf einer Ebene, auf der ich mich nicht mehr auskenne:

Skripte, die länger benötigen, um ausgeführt zu werden, werden automatisch noch einmal (ggf. mehrmals) ausgeführt.

Beispiele: Ein Newsletter an 5000 Kunden wird plötzlich (aber nicht einmal immer) noch mal versandt. Backup, der 1 Mio. Datensätze in ein Lockfile schreibt, bricht ab und schreibt wieder vom Neuen (immer und immer wieder). Ein Import von 10.000 Produkten wird manchmal 2 x ausgeführt.

Die Skripte enthalten immerhin die Anweisung

ini_set('max_execution_time', 6000);

was dann doch dicke ausreicht. Sie laufen meist zwischen 10 und 30 Minuten.

Wie kommt es zu einem solchen Phänomen? Geschieht das aufgrund einer weiteren Einstellung in PHP oder ist es ein Webservereffekt oder wie kommt so etwas zu stande und wie kann ich es abstellen? Auf mich macht das den Eindruck, als würde der Request nach einiger Zeit neu verschickt werden, weil zu lange nichts zurückkommt. Wenn es dem so ist: welche Komponente (PHP, Apache, Browser doch nicht?) verschickt es erneut und wie kann ich das verhindern, außer das ich die Schritte verstückele?

Vielen Dank im Voraus für jede konstruktive Antwort

Günter: Skripte werden im Rahmen einer Web-Applikation gestartet durch den Klick eines Benutzers (es handelt sich garantiert nicht um Mehrfachklicks)
  Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 25.09.2004, 17:02  
Gast
 
Beiträge: n/a
Standard

Hallo,

wie startest Du die skripte denn?

Wilde Vermutung: Ist da vielleicht ein scheduler im Spiel, der nach einer gewissen Zeit (z.B. 15 Minuten) meint, das Programm sei wohl abgestürzt und es einfach noch mal startet?

Andere Variante: Timeout parameter in der httpd.conf ?

Gruß,
Günter
  Mit Zitat antworten
Alt 25.09.2004, 22:11  
Gast
 
Beiträge: n/a
Standard

2 Dinge fallen mir ein:
- Ein Browser der meint er sei intelligent
Opera hat z.B. ein DNS-Timeout Einstellungen. Da der name bei start des Scriptes aufgelöst ist, wirds das nicht sein. Aber man weiss ja nie
- timeout in httpd.conf
  Mit Zitat antworten
Alt 27.09.2004, 03:26  
Erfahrener Benutzer
 
Registriert seit: 18.07.2004
Beiträge: 2.162
PHP-Kenntnisse:
Fortgeschritten
Basti
Standard

Hi.

Ich würde vorschlagen, du startest das Skript mal aus einem PHP-Skript heraus (via HTTP). Dann kannst du eine klentenseitige Fehlerquelle schonmal ausschlißen.

Dann würde ich die Laufzeit dokumentieren - also z.B. bei jedem Schleigendurchlauf eines SMTP-Request aus deinem Mail-Skript die bereits verstrichene Laufzeit in ein Logfile (über-)schreiben. Damit kannst du rausfinden, wann das Skript abbricht - es scheint ja noch andere Restrinktionen auf dem Server zu geben, als die PHP-interne Laufzeitbegrenzung. Auf welchen Ebenen man allerdings überall die Prozess-Laufzeiten und CPU-Sekunden einstellen kann, weiß ich auch nicht.

Ein Blick Wert sind sicher auch die Speicher-Grenzen. Vielleicht sind die Skripte unsauber programmiert und crachen am zugeteilten RAM-Limit?

Basti
Basti ist offline   Mit Zitat antworten
Alt 28.09.2004, 00:20  
Gast
 
Beiträge: n/a
Standard

ich handle das Problem (das ich auch habe) so - jeder Datensatz hat ein Feld "versandt".

Beim Versenden wird nun ein erster Range, sagen wir 1-100 versendet und hernach sofort das Feld "versandt" auf 1 gesetzt.
Dann lädt sich die Seite selbst neu und startet bei 101 - und so weiter.

Wenn alle versendet sind (zuversenden=0) - wird alles wieder auf 0 gesetzt, im Logbuch der Sendevorgang vermerkt und Statusbericht erstellt.
  Mit Zitat antworten
Alt 28.09.2004, 13:41  
Erfahrener Benutzer
 
Registriert seit: 18.07.2004
Beiträge: 2.162
PHP-Kenntnisse:
Fortgeschritten
Basti
Standard

...damit kannst du natürlich auch auf die Nase fallen, denn die Zeit, die du für die Ausführung benötigst hängt ja von der Auslastung des Servers und womöglich weiteren Faktoren ab. Geschickter ist es, nach jedem Durchlauf der oft zu wiederholdenen Routine zu prüfen, wie lange das Skript bereits läuft und dann rechtzeitig abzubrechen und eben möglichst kleine Einheiten zu wählen.

Und das 'Dann lädt sich die Seite selbst neu' funktioniert ja nicht. Du kannst höchstend die Bitte an einen Client schicken, die Seite nochmal aufzurufen - aber einen Client brauchst du dafür natürlich. Wenn du umgekehrt rangehst und nicht 'versendet' vermerkst, sondern 'muss noch versandt werden', dann kannst du vor dem Auftrag alle Empfänger damit und ev. mit einem Parameter, der auf einen bestimmten Autrag (was soll wann wie gemacht werden...) verweist bestücken und diesen Eintrag wieder löschen, wenn der Job getan ist. Dann ist es wurscht, wer das Skript wann wie aufruft, denn sobald es irgendwie aufgerufen wird, legt es los, die noch unerfüllten Aufgaben zu erledigen.

So kannst du diesen Job durch einen CronJob starten oder z.B. auch durch einen JavaScript-Code in einigen Webseiten, der eine bestimmte Ressource läd und dann das auch gleich wieder abbricht (dein Skript läuft ja dann weiter).

> Skripte werden im Rahmen einer Web-Applikation gestartet durch den
> Klick eines Benutzers

Nach deiner Lösung, 'humer' müsste der Benutzer ja jetzt so lange vor der Kiste sitzen bleiben, bis alle Mails versendet sind.

Mir fällt grad ein: Das Neuladen geht ja wahrscheinlich doch. Man könnte einfach in diesem Skript, das einen bestimmten Job auszuführen hat prüfen, ob der Job bereits erledigt ist. Wenn nicht, dann einen HTTP-Request mit einem kurzen Timeout an sich selber machen und dann den gewünschten Job eben soweit machen, wie es die Laufzeitlimits etc. erlauben. Wenn du sauber, also ohne Race Conditions programmierst, müsste das ja eigentlich gehen. (Vielleicht war es ja das, 'humer', das du mit 'sich selbst neu laden' meintest)

Basti

PS zum eigentlichen Thema:
Kannst ja auch mal die Option mit einer .haccess überschreiben und im Skript prüfen, ob der Wert übernommen wurde (ini_get()).
Basti ist offline   Mit Zitat antworten
Alt 29.09.2004, 00:31  
Gast
 
Beiträge: n/a
Standard

Also... das ist doch Jacke wie Hose Basti. Ob ich 1 setze und auf 0 reduziere und 0 setze und auf ein 1 erhöhe.

Was Humer meinte, ist die Methode, die ich kurzfristig auch anwenden werde, bis das Problem lokalisiert und beseitigt ist: das Skript arbeitet immer nur einen Teil der Aufgaben ab (größe am besten parametrisierbar) und macht am Ende ein Redirect auf sich selbst mit einem Parameter oder Sessionwert, der den Abarbeitungszustand enthält. Der Parameter kann sogar entfallen, wenn man in der DB flags führt, aber man erspart sich dadurch unnötige Vergleiche.

Ich sage Euch aber noch eines: Das "Mistvieh" läuft manchmal 40 Minuten lang tadellos und versendet 17000 Newsletter korrekt und ein anderes mal spinnt es schon bei 5000 (Komplexität der Newsletter ist eher gleich).

Ja ist das ein Bug der PHP-Engine? Humer, Du hast tatsächlich genau das selbe Problem? In welcher Ablaufumgebung denn?

!!!Danke für Eure Mühe!!!

Stani
  Mit Zitat antworten
Alt 29.09.2004, 01:03  
Erfahrener Benutzer
 
Registriert seit: 18.07.2004
Beiträge: 2.162
PHP-Kenntnisse:
Fortgeschritten
Basti
Standard

> Also... das ist doch Jacke wie Hose Basti. Ob ich 1 setze und auf 0
> reduziere und 0 setze und auf ein 1 erhöhe.

Es geht nicht um 0 | 1 vs. 1 | 0, sondern um 0 | 1 vs. 0 | 1 | 2 | 3 | 4 | n. Ich kenn die Umgebung ja nicht. Klar ist jedoch, wenn du zu jedem Datensatz einen Flag 'abgeschickt' setzt, dann bist du ganz anders festgelegt, als wenn du einen Flag setzt 'Job 264 ist noch nicht erledigt'. In letzterem Fall kannst du die Jobs nach belieben stapeln und eben auch flexibler abarbeiten.

Und zudem ist es generell sinniger, zuerst die Aufgabe klar zu definieren und dann abarbeiten zu lassen, als einfach mal loszulegen und dann zu dokumentieren, was bereits erledigt ist. Stell dir einfach vor, der Datenbestand würde sich in kürzeren Intervallen verändern, als du die einzelnen Datensätze abarbeiten könntest. Das ist bei einer Mailingliste natürlich schwer vorstellbar, aber hier wird der Unterschied klar, zwischen einem: 'Verschicke eine Mail an alle Benutzer, die im Moment angemeldet sind' und einem 'Verschicke solange Mails, bis du (innerhalb einer Zeitspanne t) keinen Benutzer mehr findest, der noch keine erhalten hat'. Verschtoohsch?

Basti
Basti ist offline   Mit Zitat antworten
Alt 12.10.2004, 19:09  
Gast
 
Beiträge: n/a
Standard

Man sollte grundsätzlich es vermeiden PHP als Job-Sheduler zu missbrauchen, dafür ist es schlicht und ergreifend nicht gedacht. Kommt man beispielsweise bei der Entwicklung eines ganz tollen Newsletter-Versendungstools nicht an einem Shedulling-Verhalten vorbei, ist es sehr ratsam langanhaltende Aufgaben von externen, auf dem Serversystem laufenden Skripte oder Binaries erledigen zu lassen.

Beispiel auf einem Linux-Server:
Ein Newsletter-Tool wird in PHP geschrieben. Mitarbeiter eines Unternehmens können sich in das System einloggen und eigene Newsletter-Texte verfassen, dann ein bestimmtes Pool von Adressanten aussuchen und diese mit den Mails zuspammen. Das Verfassen und Testen der Mail kann man in PHP machen, da werden noch keine Jobs ausgeführt. Das PHP-Programm speichert vor dem endgültigen Senden lediglich eine Text-Liste der Adressen (z.B. Vorname;Nachname;Email) und das vom Mitarbeiter erstellte Newsletter-Template auf die Platte ab und führt beim Abschicken ein exec() Befehl auf ein externes Batch-Programm aus. Das Versenden selbst erledigt man also mit einem eigenen Shell-Skript, das irgendwo (beispielsweise mit Hilfe einer PID-Datei) seinen eigenen Zustand (laufend, beendet, wie weit, etc.) speichern, überprüfen und bei Bedarf zurückgeben kann (PHP:shell_exec(). Das PHP-Skript kann nach dem Aktivieren des Jobs immer noch durch Seitenrefreshes den Zustand des Job-Skriptes abfragen und anzeigen (z.B. wieviel Prozent vom Newsletter schon versendet wurde). Baut man das Ganze aus, kann man mit diesem Verfahren den ganzen Vorgang sogar abbrechen und dort fortfahren wo man stehengeblieben ist etc. etc. aber das sind alles Funktionalitäten die eben in Shell-Funktionen ausgelagert werden und nicht innerhalb eines 6000sek-Timeout Monster-PHP Skriptes ausgeführt werden...

Es ist manchmal effektiver das kaputte Auto in die Werkstatt fahren zu lassen und nicht die Werkstatt um den Wagen herum aufzubauen.

Grüsse

Lev
  Mit Zitat antworten
Alt 12.10.2004, 20:03  
Erfahrener Benutzer
 
Registriert seit: 18.07.2004
Beiträge: 2.162
PHP-Kenntnisse:
Fortgeschritten
Basti
Standard

Vielen PHP-Benutzern stehen solche Möglichkeiten schlicht nicht zur Verfügung! Ich sehe nichts Verwerfliches daran, ein PHP-Skript eine Stunde lang laufen zu lassen oder es 1000 mal anzuticken, das es irgendeinen Job für mich macht. Was spricht denn nun wirklich dagegen? Deine Argumentation kann ich so nicht nachvollziehen, denn sonst wäre ich ja auch besser bedient für jedes Gästebuch als Shell-Skript zu schreiben, jedes CMS in C usw.

Basti
Basti ist offline   Mit Zitat antworten
Antwort


Themen-Optionen
Thema bewerten
Thema bewerten:

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 an
Gehe zu

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Skript "tarnen"? Off-Topic Diskussionen 17 07.08.2005 19:42
[Erledigt] DIV´s wollen nicht wie ich das will :-) HTML, Usability und Barrierefreiheit 22 28.03.2005 18:36
Skript zur Dateisuch => function??? PHP Tipps 2005 2 16.02.2005 18:03

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
php ausführungszeit, php script ausführungszeit, ein script mit langer laufzeit verhindert, php ausführzeit, script bricht ab ausführzeit zu lang php, cronjob ausführungszeit, script mit langer laufzeit, skript mit langer laufzeit, ausführungszeit php, langes skript, ausführungszeit, php ausführungszeit script, http://www.php.de/php-fortgeschrittene/9729-skript-mit-langer-ausfuehrungszeit-mehrfach-ausgefuehrt.html, php script timeout verhindern, ein skript wurde länger als die standard-timeout-zeit von 15 sekunden ausgeführt., zu langer skript, php skript laufzeit, php script mehrmals ausführen bricht ab, php skript selbst nochmal aufrufen, php ausführungsdauer

Alle Zeitangaben in WEZ +2. Es ist jetzt 23:02 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum

Creative Commons License
Dieser Inhalt ist unter einer Creative Commons-Lizenz lizenziert.