У меня есть два сценария PHP (рабочий и клиент) для выполнения задач в paralell с использованием Gearman.
Сервер работает правильно, а скрипты также, если вызывается из командной строки моего CentOS 6. Проблема возникает, когда я запускаю эти сценарии из браузера, этот ответ не возвращался.
Когда я запускаю свой клиентский скрипт, который, в свою очередь, нужен экземпляр работников, по командной строке, я получаю этот результат:
Got in: 2.04 seconds
string (20) "soidA321esa q alO321"
Но если я запустил его из своего веб- браузера, я получу его:
Got in: 0.02 seconds
NULL
Я понятия не имею, почему это работает правильно, а не в другом. Кто-нибудь случилось или знает, что что-то подобное может произойти?
Приветствую вас и благодарю вас.
PS: Прикрепленный код:
<?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();
<?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);
Я нашел решение, поскольку, как я думал, он не был связан с кодом или механизмом, который должен был быть частью конфигурации обслуживания. Дело в том, что я нашел эту дискуссию https://groups.google.com/forum/#!topic/gearman/_dW8SRWAonw и выполнил следующие команды через SHH:
[root @ localhost share] # getenforce
enforcing
[root @ localhost share] # setenforce 0
[root @ localhost share] # getenforce
permissive
Надеюсь, что кто-то поможет.
proc_open()
), которых нет у пользователя apache. Так что проверьте различные разрешения с подробным сообщением об ошибках (error_reporting(E_ALL);
иini_set('display_errors', 1);
) и посмотрите,error_reporting(E_ALL);
ли оно какие-либо ошибки.