it-swarm-es.tech

¿Cómo se puede usar subprocesos múltiples en PHP aplicaciones

¿Existe una forma realista de implementar un modelo de subprocesos múltiples en PHP ya sea de verdad, o simplemente simularlo? Hace algún tiempo, se sugirió que podría forzar al sistema operativo a cargar otra instancia del ejecutable PHP y manejar otros procesos simultáneos.

El problema con esto es que cuando el código PHP finaliza la ejecución de la instancia PHP permanece en la memoria porque no hay forma de eliminarlo desde PHP. Entonces, si estás simulando varios hilos, puedes imaginar lo que va a pasar. Por lo tanto, sigo buscando una manera de realizar subprocesos múltiples o simularlos desde PHP. ¿Algunas ideas?

363
Steve Obbayi

Multi-threading es posible en php

Sí, puedes hacer subprocesos múltiples en PHP con pthreads

Desde la PHP documentación :

pthreads es una API orientada a objetos que proporciona todas las herramientas necesarias para subprocesos múltiples en PHP. PHP aplicaciones pueden crear, leer, escribir, ejecutar y sincronizar con subprocesos, trabajadores y objetos subprocesados.

Advertencia : la extensión pthreads no se puede utilizar en un entorno de servidor web. Por lo tanto, el subprocesamiento en PHP debe permanecer solo en las aplicaciones basadas en CLI.

Prueba simple

#!/usr/bin/php
<?php
class AsyncOperation extends Thread {

    public function __construct($arg) {
        $this->arg = $arg;
    }

    public function run() {
        if ($this->arg) {
            $sleep = mt_Rand(1, 10);
            printf('%s: %s  -start -sleeps %d' . "\n", date("g:i:sa"), $this->arg, $sleep);
            sleep($sleep);
            printf('%s: %s  -finish' . "\n", date("g:i:sa"), $this->arg);
        }
    }
}

// Create a array
$stack = array();

//Initiate Multiple Thread
foreach ( range("A", "D") as $i ) {
    $stack[] = new AsyncOperation($i);
}

// Start The Threads
foreach ( $stack as $t ) {
    $t->start();
}

?>

Primer intento

12:00:06pm:     A  -start -sleeps 5
12:00:06pm:     B  -start -sleeps 3
12:00:06pm:     C  -start -sleeps 10
12:00:06pm:     D  -start -sleeps 2
12:00:08pm:     D  -finish
12:00:09pm:     B  -finish
12:00:11pm:     A  -finish
12:00:16pm:     C  -finish

Segunda carrera

12:01:36pm:     A  -start -sleeps 6
12:01:36pm:     B  -start -sleeps 1
12:01:36pm:     C  -start -sleeps 2
12:01:36pm:     D  -start -sleeps 1
12:01:37pm:     B  -finish
12:01:37pm:     D  -finish
12:01:38pm:     C  -finish
12:01:42pm:     A  -finish

Ejemplo del mundo real

error_reporting(E_ALL);
class AsyncWebRequest extends Thread {
    public $url;
    public $data;

    public function __construct($url) {
        $this->url = $url;
    }

    public function run() {
        if (($url = $this->url)) {
            /*
             * If a large amount of data is being requested, you might want to
             * fsockopen and read using usleep in between reads
             */
            $this->data = file_get_contents($url);
        } else
            printf("Thread #%lu was not provided a URL\n", $this->getThreadId());
    }
}

$t = microtime(true);
$g = new AsyncWebRequest(sprintf("http://www.google.com/?q=%s", Rand() * 10));
/* starting synchronization */
if ($g->start()) {
    printf("Request took %f seconds to start ", microtime(true) - $t);
    while ( $g->isRunning() ) {
        echo ".";
        usleep(100);
    }
    if ($g->join()) {
        printf(" and %f seconds to finish receiving %d bytes\n", microtime(true) - $t, strlen($g->data));
    } else
        printf(" and %f seconds to finish, request failed\n", microtime(true) - $t);
}
389
Baba

¿por qué no usas popen ?

for ($i=0; $i<10; $i++) {
    // open ten processes
    for ($j=0; $j<10; $j++) {
        $pipe[$j] = popen('script2.php', 'w');
    }

    // wait for them to finish
    for ($j=0; $j<10; ++$j) {
        pclose($pipe[$j]);
    }
}
34
masterb

El subprocesamiento no está disponible en el stock de PHP, pero la programación concurrente es posible mediante el uso de solicitudes HTTP como llamadas asíncronas.

Con la configuración del tiempo de espera de rizo establecido en 1 y utilizando el mismo session_id para los procesos que desea asociar entre sí, puede comunicarse con las variables de sesión como en mi ejemplo a continuación. Con este método, incluso puede cerrar su navegador y el proceso concurrente aún existe en el servidor.

No te olvides de verificar la ID de sesión correcta de esta manera:

http: //localhost/test/verifysession.php? sessionid = [the id correcto]

inicioproceso.php

$request = "http://localhost/test/process1.php?sessionid=".$_REQUEST["PHPSESSID"];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_exec($ch);
curl_close($ch);
echo $_REQUEST["PHPSESSID"];

process1.php

set_time_limit(0);

if ($_REQUEST["sessionid"])
   session_id($_REQUEST["sessionid"]);

function checkclose()
{
   global $_SESSION;
   if ($_SESSION["closesession"])
   {
       unset($_SESSION["closesession"]);
       die();
   }
}

while(!$close)
{
   session_start();
   $_SESSION["test"] = Rand();
   checkclose();
   session_write_close();
   sleep(5);
}

verifysession.php

if ($_REQUEST["sessionid"])
    session_id($_REQUEST["sessionid"]);

session_start();
var_dump($_SESSION);

closeprocess.php

if ($_REQUEST["sessionid"])
    session_id($_REQUEST["sessionid"]);

session_start();
$_SESSION["closesession"] = true;
var_dump($_SESSION);
17
Ricardo

Si bien no puedes subprocesar, tienes cierto grado de control de procesos en PHP. Los dos conjuntos de funciones que son útiles aquí son:

Funciones de control de proceso http://www.php.net/manual/en/ref.pcntl.php

Funciones POSIX http://www.php.net/manual/en/ref.posix.php

Usted podría bifurcar su proceso con pcntl_fork, devolviendo el PID del niño. Luego puede usar posix_kill para deshacerse de ese PID.

Dicho esto, si matas un proceso padre, se debe enviar una señal al proceso hijo que le indica que muera. Si el propio php no lo reconoce, puede registrar una función para administrarla y hacer una salida limpia con pcntl_signal.

11
J.D. Fitz.Gerald

Sé que esta es una pregunta antigua, pero para la búsqueda de personas, hay una extensión PECL escrita en C que le da a PHP capacidad de subprocesamiento múltiple ahora, se encuentra aquí https://github.com/krakjoe/ hilos de rosca

8
JasonDavis

el uso de hilos es posible gracias a la extensión PECLs de Pthreads

http://www.php.net/manual/en/book.pthreads.php

8
pinkal vansia

Podrías simular el enhebrado. PHP puede ejecutar procesos en segundo plano a través de popen (o proc_open). Esos procesos se pueden comunicar mediante stdin y stdout. Por supuesto, esos procesos pueden ser un programa php. Probablemente sea lo más cerca que puedas.

5
Pete

Puede usar exec () para ejecutar un script de línea de comandos (como php de línea de comandos), y si canaliza la salida a un archivo, su script no esperará a que finalice el comando.

No puedo recordar la sintaxis de la CLI de php, pero querrías algo como:

exec("/path/to/php -f '/path/to/file.php' | '/path/to/output.txt'");

Creo que algunos servidores de alojamiento compartido tienen exec () deshabilitado de forma predeterminada por razones de seguridad, pero vale la pena intentarlo.

5
Adam Hopkinson

Dependiendo de lo que estés tratando de hacer, también podrías usar curl_multi para lograrlo.

3
Sheldmandu

Sé que esto es muy antiguo, pero puedes ver http://phpthreadlib.sourceforge.net/

Es compatible con la comunicación bidireccional entre subprocesos y también tiene protecciones integradas para eliminar las hebras de los niños (evitando huérfanos).

3
Unsigned

¿Qué hay de pcntl_fork?

consulte nuestra página del manual para ver ejemplos: PHP pcntl_fork

2
Jarrod

pcntl_fork no funcionará en un entorno de servidor web si tiene modo seguro activado. En este caso, solo funcionará en la versión CLI de PHP.

2
Stilero

Puedes tener la opción de:

  1. multi_curl
  2. Uno puede usar el comando del sistema para el mismo
  3. El escenario ideal es crear una función de subprocesamiento en lenguaje C y compilar/configurar en PHP. Ahora esa función será la función de PHP.
2
Manoj Donga

La clase de tema está disponible desde PECL pthreads ≥ 2.0.0.

2
Dhananjay Kashyap

En el momento de escribir mi comentario actual, no conozco los hilos PHP. Vine a buscar la respuesta aquí mismo, pero una solución es que el programa PHP que recibe la solicitud del servidor web delega toda la formulación de la respuesta a una aplicación de consola que almacena su salida, la respuesta a la solicitud, a un archivo binario y el PHP programa que lanzó la aplicación de consola devuelve ese archivo binario byte por byte como la respuesta a la solicitud recibida. La aplicación de la consola se puede escribir en cualquier lenguaje de programación que se ejecute en el servidor, incluidos los que tienen el soporte de subprocesos adecuado, incluidos los programas C++ que utilizan OpenMP.

Un truco no confiable y sucio es usar PHP para ejecutar una aplicación de consola, "uname",

uname -a

e imprima la salida de ese comando de consola en la salida HTML para averiguar la versión exacta del software del servidor. Luego instale la misma versión exacta del software en una instancia de VirtualBox, compile/ensamble los binarios que sean totalmente independientes, preferiblemente estáticos, que desee y luego cárguelos en el servidor. Desde ese punto en adelante, la aplicación PHP puede usar esos binarios en el rol de la aplicación de consola que tiene los subprocesos múltiples adecuados. Es una solución sucia, poco confiable, alternativa a una situación, cuando el administrador del servidor no ha instalado todas las implementaciones de lenguaje de programación necesarias en el servidor. Lo que hay que tener en cuenta es que, en cada solicitud, la aplicación PHP recibe la (s) aplicación (es) de consola que finaliza/exit/get_killed.

En cuanto a lo que los administradores de servicios de alojamiento piensan de tales patrones de uso del servidor, supongo que se reduce a la cultura. En el norte de Europa, el proveedor de servicios TIENE QUE PROPORCIONAR LO QUE SE ANUNCIÓ, y si se permitió la ejecución de los comandos de la consola, se permitió la carga de archivos no maliciosos y el proveedor de servicios tiene el derecho de detener cualquier proceso del servidor después de unos minutos o incluso de 30 segundos. A continuación, los administradores del servicio de alojamiento carecen de argumentos para presentar una queja adecuada. En Estados Unidos y Europa occidental, la situación/cultura es muy diferente y creo que existe una gran posibilidad de que en los Estados Unidos y/o Europa occidental el proveedor de servicios de alojamiento se niegue a atender a los clientes de servicios de alojamiento que utilizan el truco descrito anteriormente. Esa es mi suposición, dada mi experiencia personal con los servicios de alojamiento de EE. UU. Y lo que he escuchado de otros sobre los servicios de alojamiento de Europa Occidental. En el momento de escribir mi comentario actual (2018_09_01), no sé nada sobre las normas culturales de los proveedores de servicios de alojamiento del sur de Europa, los administradores de red del sur de Europa.

0
Martin Vahi