I have two PHP script (worker and client) to perform tasks in paralell using Gearman.
The server is running properly and the scrips also, if is exectued from the command line of my CentOS 6. The problem comes when I run these scripts from the browser, this response was not returned.
When I run my client script, which in turn needed workers instance, by command line, I get this result:
Got in: 2.04 seconds
string (20) "soidA321esa q alO321"
But if I run it from your web browser, I get this one:
Got in: 0.02 seconds
NULL
I have no idea why it works correctly in one way and not another. Anyone has happened or knows something similar may be happening?
Greetings and thank you.
PS: Attached code involved:
Worker.php
<?php
class GrmWorker
{
/**
* Declaración de atributos.
*/
private $worker;
/**
* Constructor de la clase.
*/
public function __construct()
{
// Instancia un nuevo Worker.
$this->worker = new \GearmanWorker();
}
/**
* Añade un servidor de trabajo a una lista de servidores que pueden ser usados para ejecutar trabajos.
*/
public function addServer(array $servers = array())
{
// Comprueba si se envían los parámetros de servidor o se establecen los predeterminados.
if (sizeof($servers) == 0)
{
$this->worker->addServer('127.0.0.1', '4730');
}
else
{
// Recorre el array de servidores.
foreach ($servers as $server)
{
// Comprueba que los índices de los parámetros sean correctos.
if (null !== $server['host'] && null !==$server['port'])
{
$this->worker->addServer($server['host'], $server['port']);
}
else
{
throw new Exception('El array de servidores solo puede contener los índices "host" y "port".');
}
}
}
}
/**
* Registra el nombre de una función en el servidor de trabajos y especifica la llamada de retorno quer corresponde a esa función.
*/
public function addFunction($functionName, callable $function)
{
$this->worker->addFunction($functionName, $function);
}
/**
* Establece el intervalo de tiempo, en milisegundos, en el cual estará disponible el Worker.
*/
public function setTimeout($miliseconds)
{
$this->worker->setTimeout($miliseconds);
}
/**
* Retorna el tiempo actual a esperar, en milisegundos.
*/
public function timeout()
{
$this->worker->timeout();
}
/**
* Pone a funcionar el trabajador.
*/
public function work()
{
while ($this->worker->work());
}
}
/**
* Clase que contiene as funciones a declarar para el trabajador.
*/
class Functions
{
public static function reverse_cb($job)
{
sleep(2);
return strrev('123' . $job->workload());
}
}
// Instancia un nuevo trabajador.
$worker = new GrmWorker();
$worker->addServer();
$worker->setTimeout(60000);
// Declara las funciones que puede ejecutar el trabajador.
$worker->addFunction("reverse", "Functions::reverse_cb");
// Comienza a trabajar.
$worker->work();
Client.php
<?php
class GrmClient
{
// Declaración de atributos.
private $client;
private $tasks;
/**
* Constructor de la clase.
*/
public function __construct()
{
$this->client = new GearmanClient();
$this->tasks = 0;
}
/**
* Añade un servidor de trabajo a una lista de servidores que pueden ser usados para ejecutar trabajos.
*/
public function addServer(array $servers = array())
{
// Comprueba si se envían los parámetros de servidor o se establecen los predeterminados.
if (sizeof($servers) == 0)
{
$this->client->addServer('127.0.0.1', '4730');
}
else
{
// Recorre el array de servidores.
foreach ($servers as $server)
{
// Comprueba que los índices de los parámetros sean correctos.
if (null !== $server['host'] && null !== $server['port'])
{
$this->client->addServer($server['host'], $server['port']);
}
else
{
throw new Exception('El array de servidores solo puede contener los índices "host" y "port".');
}
}
}
}
/**
* Añade una tarea para ser ejecutada en paralelo.
*/
public function addTask($function_name, $workload, mixed $context = null)
{
$this->client->addTask($function_name, $workload, $context);
// Aumenta el contador de tareas a ejecutar.
$this->tasks++;
}
/**
* Ejecuta una tarea en segundo plano para ser ejecutada en paralelo.
*/
public function addTaskBackground($function_name, $workload, mixed $context = null)
{
$this->client->addTaskBackground($function_name, $workload, $context);
// Aumenta el contador de tareas a ejecutar.
$this->tasks++;
}
/**
* Añade una tarea de alta prioridad para ser ejecutada en paralelo.
*/
public function addTaskHigh($function_name, $workload, mixed $context = null)
{
$this->client->addTaskHigh($function_name, $workload, $context);
// Aumenta el contador de tareas a ejecutar.
$this->tasks++;
}
/**
* Añade una tarea de alta prioridad para ser ejecutada en segundo plano y en paralelo.
*/
public function addTaskHighBackground($function_name, $workload, mixed $context = null)
{
$this->client->addTaskHighBackground($function_name, $workload, $context);
// Aumenta el contador de tareas a ejecutar.
$this->tasks++;
}
/**
* Añade una tarea de baja prioridad para ejecutar en paralelo.
*/
public function addTaskLow($function_name, $workload, mixed $context = null)
{
$this->client->addTaskHigh($function_name, $workload, $context);
// Aumenta el contador de tareas a ejecutar.
$this->tasks++;
}
/**
* Añade una tarea de baja prioridad para ser ejecutada en segundo plano y en paralelo.
*/
public function addTaskLowBackground($function_name, $workload, mixed $context = null)
{
$this->client->addTaskHighBackground($function_name, $workload, $context);
// Aumenta el contador de tareas a ejecutar.
$this->tasks++;
}
/**
* Especifica una función a ser llamada cuando se complete una tarea. La función de llamada de retorno acepta un único argumento, un objeto GearmanTask.
*/
public function setCompleteCallback(callable $function)
{
$this->client->setCompleteCallback($function);
}
/**
* Elimina todas las funciones de retorno de llamada establecidas.
*/
public function clearCallbacks()
{
$this->client->clearCallbacks();
}
/**
* Ejecuta una lista de tareas, previamente establecidas, en paralelo.
*/
public function runTasks()
{
// Declara el array que contendrá los recursos que manejan los procesos de los workers.
$process = array();
// Comprueba si existen suficientes Workers para las tareas solicitadas.
if ($this->getNumWorkers() < $this->getNumTasks())
{
for ($i = 0; $i < $this->getNumTasks() - $this->getNumWorkers(); $i++)
{
// Pone en marcha un worker en segundo plano.
$proce = proc_open("php /var/www/html/web/Worker.php > /dev/null &",
array(
array("pipe","r"),
array("pipe","w"),
array("pipe","w")
),
$pipes);
$process[] = $proce;
}
}
// Ejecuta las tareas puestas en cola.
$this->client->runTasks();
}
/**
* Devuelve el número de tareas definidas.
*/
public function getNumTasks()
{
return $this->tasks;
}
/**
* Devuelve el número de trabajadores activos.
*/
private function getNumWorkers()
{
$workers = shell_exec ("gearadmin --workers");
$workers = explode(PHP_EOL, $workers);
return sizeof($workers) - 3;
}
}
$client = new GrmClient();
$client->addServer();
$result = null;
$client->setCompleteCallback(function(GearmanTask $task) use (&$result)
{
$result .= $task->data();
});
$client->addTask('reverse', 'Ola q ase');
$client->addTask('reverse', 'Adios');
$start = microtime(true);
$client->runTasks();
$totaltime = number_format(microtime(true) - $start, 2);
echo "Got in: " . $totaltime . " seconds \n";
var_dump($result);