我在使用Gearman时遇到一个问题,当我通过Gearman PHP扩展向它发送大型有效负载时,它将任务传输到工作人员的速度很慢。事实上,我们并没有发现有效负载有那么大(30MB)。现在所有的东西(PHP, Gearman, node)都在本地运行,所以网络访问不是瓶颈。
PHP脚本 下面是PHP客户端:ini_set('memory_limit', '1G');
$client= new GearmanClient();
$client->addServer('127.0.0.1', '4730');
$schema = file_get_contents('schema.json');
$data = file_get_contents('data.json');
$gearmanData = [
'schema' => $schema,
'data' => $data
];
echo "Encoding in JSON the payloadn";
$gearmanDataString = json_encode($gearmanData, JSON_FORCE_OBJECT);
echo "Sending job to Gearmann";
// This line takes long to execute...
$result = $client->doNormal("validateJsonSchema", $gearmanDataString);
echo "Job finishedn";
var_dump($result);
这是我的nodejs工作器,它最终会做一些事情,但空是为了证明工作器代码不是问题:
var gearmanode = require('gearmanode');
var worker = gearmanode.worker({host: '127.0.0.1' port: 4730});
worker.addFunction('validateJsonSchema', function (job) {
console.log('I will do something');
job.workComplete('Toasty!');
});
我在后台启动我的工人,然后运行我的客户端,它冻结了30秒左右,而做$client->doNormal
(就在输出发送作业到Gearman之后),并通过PHP的var_dump输出string(7) "Toasty!"
完成。所以它是有效的,但它只是长时间处理。
此外,如果我减少有效载荷(data.json)的大小,它需要更少的时间,所以有效载荷大小似乎很重要。
我试图在PHP中编写相同的工作器,结果相同:
$worker= new GearmanWorker();
$worker->addServer('127.0.0.1', '4730');
$worker->addFunction("validateJsonSchema", "validateJsonSchema");
while ($worker->work());
function validateJsonSchema($job)
{
return 'ToastyPHP!';
}
使用node.js客户端,做几乎与PHP相同的事情,它执行得快得多(约3.5秒)。是我做错了PHP版本,还是我错过了一些配置,使它更快?
node.js客户端:
var gearmanode = require('gearmanode');
var fs = require('fs');
var start = Date.now();
var client = gearmanode.client();
schema = fs.readFileSync('schema.json', 'utf8');
data = fs.readFileSync('data.json', 'utf8');
var submitData = JSON.stringify({ "data": data, "schema": schema });
// Runs much faster than PHP
var job = client.submitJob('validateJsonSchema', submitData, {background: false});
job.on('complete', function() {
console.log('RESULT >>> ' + job.response);
client.close();
var end = Date.now();
console.log(end-start + ' milliseconds'); // Always shows around 3500 milliseconds
});
知道为什么会发生这种情况吗?吉尔曼能承受这么大的载荷吗?30MB对我来说不算大
检查这段代码是否适合你,花了很少的时间来完成这项工作。
worker.php :
echo "Startingn";
$gmworker = new GearmanWorker();
# Add default server (localhost).
$gmworker->addServer('127.0.0.1', '4730');
$gmworker->addFunction("jsonValid", "jsonValid");
print "Waiting for job...n";
while ($gmworker->work()) {
if ($gmworker->returnCode() != GEARMAN_SUCCESS) {
echo "return_code: " . $gmworker->returnCode() . "n";
break;
}
}
function jsonValid($job)
{
return 'ToastyPHP!';
}
Client.php
ini_set('memory_limit', '1G');
$client = new GearmanClient();
$client->addServer('127.0.0.1', '4730');
$client->setCompleteCallback("complete");
$time = time();
echo "<pre>Sending job..." . "n";
$schema = file_get_contents('AllSets.json');
$data = file_get_contents('AllSets.json');
$gearmanData = Array(
'schema' => $schema,
'data' => $data
);
$gearmanDataString = json_encode($gearmanData, JSON_FORCE_OBJECT);
$client->addTask("jsonValid", $gearmanDataString, null, 'Json');
$client->runTasks();
echo "Job finishedn";
$endtime = time();
print "Completed in " . ($endtime - $time) . ' seconds' . "n";
function complete($task)
{
print "Unique : " . $task->unique() . "n";
print "Data : " . $task->data() . "n";
}
我使用了addTask和runTasks方法而不是donnormal。对于要发送的json数据,我使用了AllSets。来自http://mtgjson.com/大约30Mb大小的json文件(总负载),作业在1秒内完成,在尝试了大约200Mb的文件后,它花了4秒。