Gibt es in PHP eine Möglichkeit, asynchrone HTTP-Aufrufe durchzuführen? Die Antwort ist mir egal, ich möchte nur so etwas tun file_get_contents()
, aber nicht warten, bis die Anforderung abgeschlossen ist, bevor ich den Rest meines Codes ausführe. Dies wäre sehr nützlich, um "Ereignisse" einer Art in meiner Anwendung auszulösen oder lange Prozesse auszulösen.
Irgendwelche Ideen?
php
http
asynchronous
Brent
quelle
quelle
Antworten:
Die Antwort, die ich zuvor akzeptiert hatte, funktionierte nicht. Es wartete immer noch auf Antworten. Dies funktioniert jedoch, entnommen aus Wie mache ich eine asynchrone GET-Anfrage in PHP?
quelle
curl_post_async
und sogar positive Stimmen zu erhalten ...Wenn Sie das Ziel steuern, das Sie asynchron aufrufen möchten (z. B. Ihre eigene "longtask.php"), können Sie die Verbindung von diesem Ende aus schließen, und beide Skripte werden parallel ausgeführt. Es funktioniert so:
Ich habe es versucht und es funktioniert gut. Quick.php weiß jedoch nichts darüber, wie longtask.php funktioniert, es sei denn, Sie erstellen ein Kommunikationsmittel zwischen den Prozessen.
Versuchen Sie diesen Code in longtask.php, bevor Sie etwas anderes tun. Die Verbindung wird geschlossen, aber weiterhin ausgeführt (und alle Ausgaben werden unterdrückt):
Der Code wurde aus den vom Benutzer bereitgestellten Notizen des PHP-Handbuchs kopiert und etwas verbessert.
quelle
while(true);
nach Ihrem Code hinzuzufügen . Die Seite bleibt hängen, dh sie wird immer noch im Vordergrund ausgeführt.Sie können Tricks ausführen, indem Sie exec () verwenden, um etwas aufzurufen, das HTTP-Anforderungen ausführen kann, z. B.
wget
Sie müssen jedoch die gesamte Ausgabe des Programms an einen Ort wie eine Datei oder / dev / null leiten, da sonst der PHP-Prozess auf diese Ausgabe wartet .Wenn Sie den Prozess vollständig vom Apache-Thread trennen möchten, versuchen Sie Folgendes (ich bin mir nicht sicher, aber ich hoffe, Sie haben die Idee):
Es ist kein gutes Geschäft, und Sie möchten wahrscheinlich so etwas wie einen Cron-Job, der ein Heartbeat-Skript aufruft, das eine tatsächliche Datenbankereigniswarteschlange abfragt, um echte asynchrone Ereignisse auszuführen.
quelle
exec("curl $url > /dev/null 2>&1 &");
hier eine der schnellsten Lösungen. Es ist immens schneller (post_without_wait()
1,9 s für 100 Iterationen) als die Funktion (14,8 s) in der obigen "akzeptierten" Antwort. UND es ist einAb 2018 ist Guzzle die Defacto-Standardbibliothek für HTTP-Anforderungen, die in mehreren modernen Frameworks verwendet wird. Es ist in reinem PHP geschrieben und erfordert keine Installation von benutzerdefinierten Erweiterungen.
Es kann asynchrone HTTP-Aufrufe sehr gut ausführen und sie sogar bündeln, z. B. wenn Sie 100 HTTP-Aufrufe tätigen müssen, aber nicht mehr als 5 gleichzeitig ausführen möchten.
Beispiel für eine gleichzeitige Anforderung
Siehe http://docs.guzzlephp.org/en/stable/quickstart.html#concurrent-requests
quelle
quelle
&
am Ende bemerkt ?Sie können diese Bibliothek verwenden: https://github.com/stil/curl-easy
Dann ist es ziemlich einfach:
Unten sehen Sie die Konsolenausgabe des obigen Beispiels. Es wird eine einfache Live-Uhr angezeigt, die angibt, wie viel Zeitanforderung ausgeführt wird:
quelle
Fake eine Anfrage Abtreibung mit
CURL
einem Low setzenCURLOPT_TIMEOUT_MS
so eingestellt
ignore_user_abort(true)
, dass die Verarbeitung nach dem Schließen der Verbindung fortgesetzt wird.Bei dieser Methode muss die Verbindungsbehandlung nicht über Header und Puffer implementiert werden, was zu stark von Betriebssystem, Browser und PHP-Version abhängt
Master-Prozess
Hintergrundprozess
NB
Ressourcen
Curl Timeout weniger als 1000ms schlägt immer fehl?
http://www.php.net/manual/en/function.curl-setopt.php#104597
http://php.net/manual/en/features.connection-handling.php
quelle
lass mich dir meinen Weg zeigen :)
benötigt nodejs auf dem Server installiert
(Mein Server sendet 1000 https Get-Anfrage dauert nur 2 Sekunden)
url.php:
urlscript.js>
quelle
Die Swoole-Erweiterung. https://github.com/matyhtf/swoole Asynchrones und gleichzeitiges Netzwerkframework für PHP.
quelle
Sie können nicht blockierende Sockets und eine der Pecl-Erweiterungen für PHP verwenden:
Sie können eine Bibliothek verwenden, die Ihnen eine Abstraktionsschicht zwischen Ihrem Code und einer pecl-Erweiterung bietet: https://github.com/reactphp/event-loop
Sie können auch einen asynchronen http-Client verwenden, der auf der vorherigen Bibliothek basiert: https://github.com/reactphp/http-client
Weitere Bibliotheken von ReactPHP finden Sie unter: http://reactphp.org
Seien Sie vorsichtig mit einem asynchronen Modell. Ich empfehle, dieses Video auf Youtube zu sehen: http://www.youtube.com/watch?v=MWNcItWuKpI
quelle
quelle
Ereigniserweiterung
Event- Erweiterung ist sehr angemessen. Es ist ein Port der Libevent- Bibliothek, der für ereignisgesteuerte E / A, hauptsächlich für die Vernetzung, konzipiert ist.
Ich habe einen Beispiel-HTTP-Client geschrieben, mit dem eine Reihe von HTTP-Anforderungen geplant und asynchron ausgeführt werden können.
Dies ist eine Beispiel-HTTP-Clientklasse, die auf der Ereigniserweiterung basiert .
Die Klasse ermöglicht es, eine Reihe von HTTP-Anforderungen zu planen und diese dann asynchron auszuführen.
http-client.php
test.php
Dies ist ein Beispielskript auf der Serverseite.
Verwendung
Beispielausgabe
(Beschnitten.)
Beachten Sie, dass der Code für die Langzeitverarbeitung in der CLI SAPI ausgelegt ist .
Erwägen Sie für benutzerdefinierte Protokolle die Verwendung einer API auf niedriger Ebene, dh Pufferereignisse , Puffer . Für die SSL / TLS-Kommunikation würde ich die Low-Level-API in Verbindung mit dem SSL-Kontext von Event empfehlen . Beispiele:
Obwohl die HTTP-API von Libevent einfach ist, ist sie nicht so flexibel wie Pufferereignisse. Beispielsweise unterstützt die HTTP-API derzeit keine benutzerdefinierten HTTP-Methoden. Es ist jedoch möglich, praktisch jedes Protokoll mithilfe der Low-Level-API zu implementieren.
Ev Erweiterung
Ich habe auch ein Beispiel eines anderen HTTP-Clients mit der Erweiterung Ev mit Sockets im nicht blockierenden Modus geschrieben . Der Code ist etwas ausführlicher als das auf Event basierende Beispiel, da Ev eine Allzweck-Ereignisschleife ist. Es bietet keine netzwerkspezifischen Funktionen, aber es ist
EvIo
Watcher kann insbesondere einen in die Socket-Ressource gekapselten Dateideskriptor abhören.Dies ist ein Beispiel für einen HTTP-Client, der auf der Ev- Erweiterung basiert .
Die Ev-Erweiterung implementiert eine einfache, aber leistungsstarke Allzweck-Ereignisschleife. Es bietet keine netzwerkspezifischen Beobachter, aber der E / A-Beobachter kann für die asynchrone Verarbeitung von Sockets verwendet werden .
Der folgende Code zeigt, wie HTTP-Anforderungen für die parallele Verarbeitung geplant werden können.
http-client.php
Testen
Angenommen, das
http://my-host.local/test.php
Skript druckt den Speicherauszug von$_GET
:Dann ist die Ausgabe des
php http-client.php
Befehls wie folgt:(getrimmt)
Beachten Sie , dass in PHP 5 die Steckdosen - Erweiterung für log Warnungen können
EINPROGRESS
,EAGAIN
undEWOULDBLOCK
errno
Werte. Es ist möglich, die Protokolle mit auszuschaltenIn Bezug auf "den Rest" des Kodex
Der Code, der parallel zu den Netzwerkanforderungen ausgeführt werden soll, kann beispielsweise innerhalb des Rückrufs eines Ereignis-Timers oder des Leerlauf-Watchers von Ev ausgeführt werden . Sie können es leicht herausfinden, indem Sie sich die oben genannten Beispiele ansehen. Ansonsten füge ich noch ein Beispiel hinzu :)
quelle
Hier ist ein funktionierendes Beispiel. Führen Sie es einfach aus und öffnen Sie die Datei storage.txt, um das magische Ergebnis zu überprüfen
quelle
Hier ist meine eigene PHP-Funktion, wenn ich POST zu einer bestimmten URL einer beliebigen Seite mache .... Beispiel: *** Verwendung meiner Funktion ...
quelle
ReactPHP asynchroner http-Client
https://github.com/shuchkin/react-http-client
Installation über Composer
Async HTTP GET
Führen Sie PHP im CLI-Modus aus
quelle
Ich finde dieses Paket sehr nützlich und sehr einfach: https://github.com/amphp/parallel-functions
Es werden alle 3 URLs parallel geladen. Sie können im Abschluss auch Klasseninstanzmethoden verwenden.
Zum Beispiel verwende ich die Laravel-Erweiterung basierend auf diesem Paket https://github.com/spatie/laravel-collection-macros#parallelmap
Hier ist mein Code:
Es lädt alle benötigten Daten in 10 parallelen Threads und statt 50 Sekunden ohne Asynchronisierung in nur 8 Sekunden.
quelle
Symfony HttpClient ist asynchron https://symfony.com/doc/current/components/http_client.html .
Zum Beispiel können Sie
quelle
Das Zeitlimit kann in Millisekunden festgelegt werden, siehe "CURLOPT_CONNECTTIMEOUT_MS" unter http://www.php.net/manual/en/function.curl-setopt
quelle