Weiß jemand, wie man die Verbindung schließt (außer einfach flush()
), aber danach noch einige Code ausführen kann.
Ich möchte nicht, dass der Client den langen Prozess sieht, der nach Abschluss der Seite stattfinden kann.
Weiß jemand, wie man die Verbindung schließt (außer einfach flush()
), aber danach noch einige Code ausführen kann.
Ich möchte nicht, dass der Client den langen Prozess sieht, der nach Abschluss der Seite stattfinden kann.
Sie möchten vielleicht pcntl_fork()
ansehen - es ermöglicht Ihnen, Ihr aktuelles Skript zu verzweigen und in einem separaten Thread auszuführen.
Ich habe es in einem Projekt verwendet, bei dem ein Benutzer eine Datei hochgeladen hat und das Skript dann verschiedene Operationen damit durchgeführt hat, einschließlich der Kommunikation mit einem Server eines Drittanbieters, was lange dauern könnte. Nach dem initialen Upload hat das Skript verzweigt und dem Benutzer die nächste Seite angezeigt, und das Elternteil hat sich selbst beendet. Das Kind hat dann weiter ausgeführt und wurde von der zurückgegebenen Seite über seinen Status mit AJAX abgefragt. Es hat die Anwendung viel reaktionsfähiger gemacht, und der Benutzer hat während der Ausführung Feedback zum Status erhalten.
Dieser Link enthält weitere Informationen zur Verwendung:
Wenn Sie pcntl_fork
nicht verwenden können, können Sie immer schnell eine Seite zurückgeben, die eine AJAX-Anfrage auslöst, um mehr Elemente aus einer Warteschlange auszuführen.
mvds weist auf Folgendes hin (was in einer spezifischen Serverkonfiguration anwendbar sein kann): Gabeln Sie nicht den gesamten Apache-Webserver, sondern starten Sie stattdessen einen separaten Prozess. Lassen Sie diesen Prozess eine Kindsgabel erstellen, die weiterläuft. Suchen Sie nach
proc_open
um eine vollständige fd-Interaktion zwischen Ihrem PHP-Skript und dem Prozess zu erhalten.
Beachten Sie, dass Sie pcntl_fork() (in diesem Kontext) nur mit einem benutzerdefinierten HTTP-Server verwenden können, der selbst in PHP geschrieben ist - daher kann diese Antwort typischerweise nur etwa 0,0001% der Zeit verwendet werden ;)
Dann gabelst du den gesamten Apache-Dämon, denke ich. Das ist kein schöner Anblick und wahrscheinlich nicht die beabsichtigte Verwendung eines Apache-Moduls...
Ich glaube, dass es den Apache-Worker-Prozess aufgabelt, von dem der Prozess einer von vielen wäre (wenn auch standardmäßig viel zu viele). Dies, zusammen mit der Tatsache, dass der durchschnittliche Linux-Server ziemlich gut darin ist, Prozesse aufzuzweigen, lässt mich erwarten, dass es nicht so problematisch ist, wie man erwarten könnte. Meine Erfahrung war allerdings nicht für eine missionkritische App. Wie ich jedoch sage, ist dies nur der kleinere Teil der Lösung -- die Hauptarchitektur der Lösung ist die ordnungsgemäße Einrichtung des Client-Server-Modells.
Ich möchte nicht, dass der Kunde den langen Prozess sieht, der nach Abschluss der Seite stattfinden kann.
Leider ist die Seite erst nach Abschluss des langen Prozesses fertig - daher ist das, was du verlangst, (aus dem von dir angedeuteten Grund) leider unmöglich umzusetzen. Ich fürchte.
Das entscheidende hier, wie von Jhongs Antwort hervorgehoben und von animusens Kommentar indirekt angedeutet, ist, dass der Sinn dessen, was wir als Webentwickler mit HTTP tun, darin besteht, so schnell wie möglich auf eine Anfrage zu reagieren /Ende - das ist alles, also wenn du etwas anderes machst, dann liegt das an einer Designentscheidung, die vielleicht etwas besser hätte sein können :)
Typischerweise übernimmst du die zusätzliche Aufgabe, die du nach der Rückgabe der 'Seite' erledigst, und übergibst sie einem anderen Prozess, normalerweise bedeutet das, dass du die Aufgabe in eine Job-Warteschlange legst und ein CLI-Dämon oder ein Cron-Job sie übernimmt und das Notwendige tut.
Die genaue Lösung ist spezifisch für das, was du tust, und die Antwort auf eine andere (Gruppe von) Fragen; aber für diese hier kommt es darauf an: nein, du kannst die Verbindung nicht schließen, und es wird empfohlen, den lang laufenden Prozess aus diesem Skript/dieser Seite auszulagern.
Schauen Sie sich die _ignore_user_abort
-Einstellung von PHP_ an. Sie können sie mit der ignore_user_abort()
-Funktion setzen.
Ein Beispiel für (optionale) Verwendung wurde (und wurde vom OP als funktionierend gemeldet) in der folgenden Duplikatfrage gegeben:
Es verweist im Wesentlichen auf Benutzerhinweise im PHP-Handbuch. Eine zentrale ist
die auch die Basis für die folgenden beiden ist, die ich Ihnen empfehle anzuschauen:
Das ist die tatsächlich beste Antwort. Er erklärt, dass der Kunde das Ergebnis des Prozesses nicht kennen muss, daher muss er keine Verzweigungen, Warteschlangen oder ähnliche Dinge verwenden.
@pjbeardsley: Eigentlich ist dies nicht die beste Antwort, da sie mit einigen unbemerkten Problemen einhergeht: Erstens ist das _ingnore_user_abort
_ laut den verlinkten Quellen optional, wird jedoch zuerst genannt und ist notwendig. Zweitens wurde die hier präsentierte Antwort bereits früher gegeben und war nicht verlinkt. Außerdem fehlte der Quellcode (das war auch ein Problem für den verlinkten Duplikat, wurde dort jedoch jetzt behoben). Die verlinkten Beispiele tun jedoch in einigen Webserver / PHP-Konfigurationen gut, was du sagst, und sind auf gewisse Weise eine Art üblich. Also ist es auch keine völlig schlechte Antwort.
Dies ist wahrscheinlich eine Ergänzung zu einer vorhandenen Antwort, insbesondere zu der ausführlicheren Befürchtung, dass pcntl_fork in einer sehr speziellen Apache + PHP-Konfiguration innerhalb des Apache SAPI-Moduls etwas Schlechtes/ressourcenintensives tun könnte. Dies sollte ein Kommentar zur bestehenden Antwort sein oder eine zusätzliche Bearbeitung für die Dinge, über die man nachdenken sollte, wenn man diese Antwort verwendet, keine zusätzliche Antwort, weil es nicht wirklich klar ist, wofür es gut ist. Ich habe es zusammengeführt und bitte Sie, es zu löschen. - Außerdem, während ich darüber nachdenke, sollte es eine Referenz geben, die dies besser erklärt, wie z.B. einen Link, vielleicht zu fork
in PHP.
@hakre Ich stimme dir nicht zu. Die Frage ist "wie führe ich Code aus, nachdem ich ein PHP-Skript ausgeführt habe" und die Antwort lautet "stattdessen einen separaten Prozess starten. Lassen Sie diesen Prozess einen Kindprozess abspalten, der weiterläuft. Suchen Sie nach proc_open, um eine vollständige FD-Interaktion zwischen Ihrem PHP-Skript und dem Prozess zu erhalten."
Wir haben dieses Problem gelöst, indem wir die Arbeit, die erledigt werden muss, in eine Job-Warteschlange eingefügt haben und dann ein Cron-Skript regelmäßig die Backend-Jobs abholt. Wahrscheinlich nicht genau das, was du brauchst, aber es funktioniert sehr gut für datenintensive Prozesse.
(Du könntest auch die Job-Warteschlange von Zend Server verwenden, wenn du ein Bündel Geld hast und eine erprobte Lösung möchtest)
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
1 Stimmen
Warum würdest du das brauchen? PHP benötigt nur Millisekunden, um ein normales Skript auszuführen. Alles, was länger dauert, sollte nicht für die Allgemeinheit zugänglich sein.
0 Stimmen
Animuson, obwohl ich im Allgemeinen mit Ihrer Aussage übereinstimme, wissen wir nicht, ob diese Anwendung/Website für die breite Öffentlichkeit zugänglich ist oder nicht. Es könnte sehr gut eine Anwendung sein, die intern irgendwo läuft. Deshalb sehe ich nicht die Relevanz Ihres Kommentars...