¿Hay alguna manera en PHP de hacer llamadas HTTP asincrónicas? No me importa la respuesta, solo quiero hacer algo como file_get_contents()
, pero no esperar a que finalice la solicitud antes de ejecutar el resto de mi código. Esto sería muy útil para activar "eventos" de un tipo en mi aplicación o desencadenar procesos largos.
¿Algunas ideas?
php
http
asynchronous
Brent
fuente
fuente
Respuestas:
La respuesta que había aceptado anteriormente no funcionó. Todavía esperaba respuestas. Sin embargo, esto funciona, tomado de ¿Cómo hago una solicitud GET asincrónica en PHP?
fuente
curl_post_async
y obtener incluso votos a favor ...Si controla el destino al que desea llamar de forma asíncrona (por ejemplo, su propio "longtask.php"), puede cerrar la conexión desde ese extremo y ambos scripts se ejecutarán en paralelo. Funciona así:
He intentado esto y funciona bien. Pero quick.php no sabrá nada sobre el funcionamiento de longtask.php, a menos que cree algún medio de comunicación entre los procesos.
Pruebe este código en longtask.php, antes de hacer cualquier otra cosa. Cerrará la conexión, pero seguirá ejecutándose (y suprimirá cualquier salida):
El código se copia de las notas aportadas por el usuario del manual de PHP y se mejora un poco.
fuente
while(true);
después de tu código. La página se bloqueará, esto significa que todavía se está ejecutando en primer plano.Puede hacer trucos usando exec () para invocar algo que puede hacer solicitudes HTTP, como
wget
, pero debe dirigir toda la salida del programa a algún lugar, como un archivo o / dev / null, de lo contrario el proceso PHP esperará esa salida .Si desea separar el proceso del hilo de Apache por completo, intente algo como (no estoy seguro de esto, pero espero que tenga la idea):
No es un buen negocio, y es probable que desee algo como un trabajo cron que invoca un script de latido que sondea una cola de eventos de base de datos real para hacer eventos asincrónicos reales.
fuente
exec("curl $url > /dev/null 2>&1 &");
es una de las soluciones más rápidas aquí. Es inmensamente más rápido (1.9s para 100 iteraciones) que lapost_without_wait()
función (14.8s) en la respuesta "aceptada" anterior. Y es unaA partir de 2018, Guzzle ha convertido en la biblioteca estándar de facto para solicitudes HTTP, utilizada en varios marcos modernos. Está escrito en PHP puro y no requiere la instalación de extensiones personalizadas.
Puede hacer llamadas HTTP asincrónicas muy bien e incluso agruparlas como cuando necesita hacer 100 llamadas HTTP, pero no desea ejecutar más de 5 a la vez.
Ejemplo de solicitud concurrente
Ver http://docs.guzzlephp.org/en/stable/quickstart.html#concurrent-requests
fuente
fuente
&
al final?Puedes usar esta biblioteca: https://github.com/stil/curl-easy
Es bastante sencillo entonces:
A continuación puede ver la salida de la consola del ejemplo anterior. Mostrará un reloj en vivo simple que indica cuánto tiempo se está ejecutando la solicitud:
fuente
Falsifica una solicitud de aborto usando
CURL
una configuración bajaCURLOPT_TIMEOUT_MS
configurado
ignore_user_abort(true)
para seguir procesando después de cerrar la conexión.Con este método, no es necesario implementar el manejo de la conexión a través de encabezados y búfer demasiado dependientes de la versión del sistema operativo, navegador y PHP
Proceso maestro
Proceso de fondo
nótese bien
Recursos
¿el tiempo de espera del enrollamiento menos de 1000ms siempre falla?
http://www.php.net/manual/en/function.curl-setopt.php#104597
http://php.net/manual/en/features.connection-handling.php
fuente
déjame mostrarte mi camino :)
necesita nodejs instalado en el servidor
(mi servidor envía 1000 solicitudes de obtención de https solo toma 2 segundos)
url.php:
urlscript.js>
fuente
La extensión del swoole. https://github.com/matyhtf/swoole Marco de red asincrónico y concurrente para PHP.
fuente
Puede usar sockets sin bloqueo y una de las extensiones pecl para PHP:
Puede usar la biblioteca que le brinda una capa de abstracción entre su código y una extensión pecl: https://github.com/reactphp/event-loop
También puede usar un cliente http asíncrono, basado en la biblioteca anterior: https://github.com/reactphp/http-client
Ver otras bibliotecas de ReactPHP: http://reactphp.org
Tenga cuidado con un modelo asincrónico. Recomiendo ver este video en youtube: http://www.youtube.com/watch?v=MWNcItWuKpI
fuente
fuente
Extensión de evento
La extensión del evento es muy apropiada. Es un puerto de la biblioteca Libevent que está diseñado para E / S controladas por eventos, principalmente para redes.
He escrito un cliente HTTP de muestra que permite programar una serie de solicitudes HTTP y ejecutarlas de forma asincrónica.
Esta es una clase de cliente HTTP de muestra basada en la extensión de evento .
La clase permite programar una serie de solicitudes HTTP y luego ejecutarlas de forma asincrónica.
http-client.php
prueba.php
Este es un script de muestra en el lado del servidor.
Uso
Salida de muestra
(Recortado)
Tenga en cuenta que el código está diseñado para el procesamiento a largo plazo en el CLI SAPI .
Para protocolos personalizados, considere usar API de bajo nivel, es decir , eventos de búfer , búferes . Para las comunicaciones SSL / TLS, recomendaría la API de bajo nivel junto con el contexto ssl de Event . Ejemplos:
Aunque la API HTTP de Libevent es simple, no es tan flexible como los eventos de búfer. Por ejemplo, la API HTTP actualmente no admite métodos HTTP personalizados. Pero es posible implementar prácticamente cualquier protocolo utilizando la API de bajo nivel.
Ev extensión
También he escrito una muestra de otro cliente HTTP que usa la extensión Ev con sockets en modo sin bloqueo . El código es un poco más detallado que el ejemplo basado en Evento, porque Ev es un bucle de evento de propósito general. No proporciona funciones específicas de la red, pero su
EvIo
observador es capaz de escuchar un descriptor de archivo encapsulado en el recurso de socket, en particular.Este es un cliente HTTP de muestra basado en la extensión Ev .
La extensión Ev implementa un bucle de evento de propósito general simple pero potente. No proporciona observadores específicos de la red, pero su observador de E / S se puede usar para el procesamiento asíncrono de sockets .
El siguiente código muestra cómo se pueden programar las solicitudes HTTP para el procesamiento paralelo.
http-client.php
Pruebas
Supongamos que el
http://my-host.local/test.php
script está imprimiendo el volcado de$_GET
:Entonces la salida del
php http-client.php
comando será similar a la siguiente:(recortado)
Tenga en cuenta, en PHP 5, la tomas de extensión puede registrar advertencias para
EINPROGRESS
,EAGAIN
yEWOULDBLOCK
errno
valores. Es posible apagar los registros conSobre "el resto" del Código
El código que se supone que debe ejecutarse en paralelo con las solicitudes de red puede ejecutarse dentro de la devolución de llamada de un temporizador de eventos , o el observador inactivo de Ev , por ejemplo. Puede resolverlo fácilmente observando las muestras mencionadas anteriormente. De lo contrario, agregaré otro ejemplo :)
fuente
Aquí hay un ejemplo de trabajo, simplemente ejecútelo y abra storage.txt luego, para verificar el resultado mágico
fuente
Aquí está mi propia función PHP cuando hago POST a una URL específica de cualquier página ... Ejemplo: *** uso de mi función ...
fuente
Cliente http asíncrono ReactPHP
https://github.com/shuchkin/react-http-client
Instalar a través de Composer
HTTP asíncrono GET
Ejecute php en modo CLI
fuente
Este paquete me parece bastante útil y muy simple: https://github.com/amphp/parallel-functions
Cargará las 3 URL en paralelo. También puede usar métodos de instancia de clase en el cierre.
Por ejemplo, uso la extensión Laravel basada en este paquete https://github.com/spatie/laravel-collection-macros#parallelmap
Aquí está mi código:
Carga todos los datos necesarios en 10 subprocesos paralelos y, en lugar de 50 segundos sin asíncrono, terminó en solo 8 segundos.
fuente
Symfony HttpClient es asíncrono https://symfony.com/doc/current/components/http_client.html .
Por ejemplo puedes
fuente
Bueno, el tiempo de espera se puede configurar en milisegundos, consulte "CURLOPT_CONNECTTIMEOUT_MS" en http://www.php.net/manual/en/function.curl-setopt
fuente