PHP: Wie man Informationen zu einem wartenden Skript zurückgibt und die Verarbeitung fortsetzt


6

Angenommen, es gibt zwei Skripts Requester.php und Provider.php, und Requester benötigt die Verarbeitung vom Provider und macht eine http-Anfrage an ihn (Provider.php? Data = " Daten"). In dieser Situation findet Provider schnell die Antwort, aber um das System zu warten, muss es verschiedene Aktualisierungen in der gesamten Datenbank durchführen. Gibt es eine Möglichkeit, den Wert sofort an Anforderer zurückzugeben und die Verarbeitung im Provider fortzusetzen?

Psuedo-Code

Provider.php 
{ 
    $answer = getAnswer($_GET['data']); 
    echo $answer; 
    //SIGNAL TO REQUESTER THAT WE ARE FINISHED 
    processDBUpdates(); 
    return; 
} 
1

Sie möchten grundsätzlich das Ende von 1 Prozess signalisieren (Rückkehr zum ursprünglichen Requester.php) und einen neuen Prozess erzeugen (Ende Provider.php). Es gibt wahrscheinlich einen eleganteren Weg, dies zu erreichen, aber ich habe es auf verschiedene Arten geschafft. Sie alle führen grundsätzlich dazu, dass ein Befehl ausgeführt wird, um den zweiten Prozess abzuschalten.

die folgenden > /dev/null 2>&1 & bis zum Ende des Befehls Hinzufügen ermöglicht es, ohne Hemmung die tatsächliche Ausführung des aktuellen Skripts

So etwas wie die folgenden im Hintergrund laufen zu lassen für Sie arbeiten kann:

exec("wget -O - \"$url\" > /dev/null 2>&1 &"); 

- obwohl Sie es auch als Kommandozeilen-PHP-Prozess tun könnten.

Sie können auch die Informationen speichern, die verarbeitet werden müssen, und die verbleibende Verarbeitung für einen Cron-Job bearbeiten, der die gleiche Funktionalität wieder herstellt, ohne dass eine Exec ausgeführt werden muss.


2

Sie können den Ausgabepuffer mit dem flush() Befehl spülen.
Lesen Sie die Kommentare in der PHP manual für weitere Informationen


0

Split der Anbieter in zwei: ProviderCore und ProviderInterface. In ProviderInterface tun Sie einfach den "schnellen und einfachen" Teil, speichern Sie auch ein Flag in der Datenbank, dass die letzte Anfrage noch nicht verarbeitet wurde. Führen Sie ProviderCore als Cron-Job aus, der nach diesem Flag sucht und die Verarbeitung abschließt. Wenn es nichts zu tun gibt, wird ProviderCore beendet und in (sagen wir) 2 Minuten erneut versucht.


1

Ich denke, Sie müssen auf dem Anbieter die Daten senden (achten Sie darauf, zu flush), und dann auf dem Requester, verwenden Sie fopen/fread eine erwartete Menge an Daten zu lesen, so dass Sie die Verbindung zu den Anbieter und weiter. Wenn Sie keine zu erwartende Datenmenge angeben, würde ich denken, dass der Anforderer dort sitzen würde und darauf warten würde, dass der Provider die Verbindung schließt, was wahrscheinlich erst am Ende der Verbindung geschieht (dh alle sekundären arbeitsintensiven Vorgänge) Aufgaben sind abgeschlossen). Sie müssen ein paar POC's ausprobieren.

Viel Glück.


2

Ich benutze this code zum Ausführen eines Prozesses im Hintergrund (funktioniert unter Linux).

Der Prozess wird mit seiner Ausgabe in eine Datei umgeleitet.

Auf diese Weise, wenn ich Status auf dem Prozess anzeigen muss, ist es nur eine Frage des Schreibens einer kleinen Menge Code zu lesen und den Inhalt der Ausgabedatei anzuzeigen.

Ich mag diesen Ansatz, weil es bedeutet, dass Sie den Browser vollständig schließen und später einfach wiederkommen können, um den Status zu überprüfen.


0

Ich gehe hier aus, aber vielleicht sollten Sie cURL versuchen oder einen Socket verwenden, um den Requester zu aktualisieren?


0

Sie könnten einen anderen PHP-Prozess in Provider.php mit pcntl_fork starten()

Provider.php 
{ 
    // Fork process 
    $pid = pcntl_fork(); 

    // You are now running both a daemon process and the parent process 
    // through the rest of the code below 

    if ($pid > 0) { 
     // PARENT Process 
     $answer = getAnswer($_GET['data']); 
     echo $answer;  
     //SIGNAL TO REQUESTER THAT WE ARE FINISHED 
     return; 
    } 

    if ($pid == 0) { 
     // DAEMON Process 
     processDBUpdates(); 
     return; 
    } 

    // If you get here the daemon process failed to start 
    handleDaemonErrorCondition(); 
    return; 

}