PHP Asíncrono, sin morir en el intento (Parte 2)

En el post anterioraclaramos algunos conceptos sobre la computación concurrente y procesos asíncronos. En esta oportunidad nos enfocaremos en librerías, patrones y soluciones que podemos implementar en PHP. Sin más, empecemos:

Threads en php con ampthread

Esta solución consiste en usar threads en php, pero haciendo uso de la librería ampthread para manipularlos de forma más efectiva. Entre otras cosas, nos permite hacer uso de promises tal cual se hacen en javascript. Esto nos permitiría manipular mejor los casos de éxito o fracaso de procesos que ya sean asíncronos.

El problema principal de esta opción es que es necesario usar la extensión de pecl pthread (https://pecl.php.net/package/threads) que requiere compilar php con ZTS (Zend Thread Safety) que por defecto no está incluido, esto es complicado porque requeriría eliminar la versión que tenemos de php y compilarla desde cero.

ampthread más que una implementación de arquitectura asíncrona es un workaround para ‘simular’ el comportamiento y manipularlo con funciones y conceptos tomados de arquitecturas que si son asíncronas. Por debajo usa threads, y ya vimos en la primera parte de este post que no es lo mismo.

ReactPHP

Esta librería es de lo más interesante que he encontrado. Permite manejar tareas asíncronas tal cual en javascript, usando el mismo principio non-blocking de Nodejs.  Implementa un event loop para ‘escuchar’ los eventos de éxito/error de las tareas asíncronas. Además nos ofrece diferentes herramientas ya desarrolladas que trabajan de forma asíncrona, como un cliente http, un websocket (Ratchet) y un cliente para Redis.

¿Qué puedo hacer con ReactPHP?

Podemos manipular procesos asíncronos e implementar las utilidades que nos ofrece la librería

Veamos un ejemplo de un cliente HTTP

require 'vendor/autoload.php';
 
 $app = function ($request, $response) {
    $response->writeHead(200, array('Content-Type' => 'text/plain'));
    $response->end("Hello World\n");
 };
 
 $loop = React\EventLoop\Factory::create();
 $socket = new React\Socket\Server($loop);
 $http = new React\Http\Server($socket, $loop);
 
 $http->on('request', $app);
 echo "Server running at http://127.0.0.1:1337\n";
 
 $socket->listen(1337);
 $loop->run();

Para ejecutar este código, necesitamos instalar React, podemos hacerlo de la siguiente forma:

% composer init --require=react/http:0.3.* -n
 % composer install

Luego, podemos guardar el código PHP mostrado anteriormente en un archivo y ejecutarlo desde la terminal con el siguiente comando

php react-server.php

Así, ejecutaremos el servidor web en el puerto especificado, que nos retornará la siguiente respuesta

Server running at http://127.0.0.1:1337

AsyncTask

Una solución sencilla es ésta libreŕia que permite convertir cualquier función/proceso en una tarea asíncrona, así como permite la inclusión de hooks de ejecución antes y después de la misma.

Para implementarla necesitamos los siguientes requerimientos

PHP version ~5.3.3

Módulos pcntl y posix instalados

Todas las funciones pcntl, posix y shm eliminadas de la directiva disable_functions del php.ini. Los podemos deshabilitar editando la siguiente línea de nuestro php.ini, es decir eliminándolas de la siguiente línea

disable_functions =

Para realizar la instalación podemos hacerlo con composer

composer require dmamontov/asynctask ~1.0.5

Ejemplo de implementación

class TestTask extends AsyncTask
 {

  //Hook que se ejecuta antes de la tarea principal
    protected function onPreExecute()
    {
    }
 
    protected function doInBackground($parameters)
    {
      //El código dentro de esta función se ejecutará de forma asíncrona
        return $parameters;
    }

  //Hook que se ejecuta después de la tarea principal
  protected function onPostExecute($result)
  {
     echo $result;
  }
}

$task = new TestTask(); $task->execute('test');

Es importante saber que las funciones onPreExecute y onPostExecute son funciones definidas de la clase AsyncTask y deben mantener el mismo nombre, así como la función doInBackground que es donde se ejecuta la tarea asíncrona

Conclusión y factibilidad

Por tanto, podemos concluir que para implementar funcionalidades asíncronas en nuestro código debemos analizar bien para escoger que herramienta/librería usar. Recordemos que estas librerías no son más que workarounds sobre PHP que permiten la “simulación” de ejecución asíncrona.

Otros enlaces de interés

https://github.com/icicleio/icicle

http://kraken-php.com/

https://github.com/recoilphp

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

w

Conectando a %s