【发布时间】:2015-11-23 12:49:00
【问题描述】:
我有两个 PHP 脚本(worker 和 client)使用 Gearman 并行执行任务。
服务器运行正常,如果从我的 CentOS 6 的命令行执行,脚本也运行正常。当我从 浏览器 运行这些脚本时,问题就出现了,则未返回此响应。
当我通过命令行运行我的客户端脚本时,它又需要worker实例,我得到这个结果:
Got in: 2.04 seconds
string (20) "soidA321esa q alO321"
但如果我从您的网络浏览器运行它,我会得到这个:
Got in: 0.02 seconds
NULL
我不知道为什么它以一种方式正常工作而不是另一种方式。 有人发生过或知道可能会发生类似的事情吗?
您好,谢谢。
PS:所涉及的附加代码:
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();
客户端.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);
【问题讨论】:
-
当通过浏览器调用时,脚本要快得多,因此可能不是每个代码都已运行。可能您将拥有一个具有 shell 访问权限的用户。该用户可能拥有 apache 用户没有的权限(如
proc_open())。因此,请使用详细的错误消息(error_reporting(E_ALL);和ini_set('display_errors', 1);)检查不同的权限,看看它是否会引发任何错误。 -
谢谢 @Jan 我明白了。一旦我显示发生的错误,我返回以下 error:Warning: GearmanClient::runTasks(): send_packet(GEARMAN_COULD_NOT_CONNECT) Failed to send server-options packet -> libgearman/connection.cc :485 在 /var/www/html/web/Client.php 第 157 行 ¿你知道它是关于什么的吗?
-
未设置端口 (4730) 时会出现这种情况,请参阅here on SO for more information。
-
嗨@Jan 在代码中,添加服务器时明确声明连接端口。 addServer('127.0.0.1', '4730') THX
-
请接受您自己的答案并删除“已解决...”