【发布时间】:2015-08-06 19:25:46
【问题描述】:
我在使用 Gearman 时遇到问题,当我通过 Gearman PHP 扩展向它发送大量有效负载时,将任务传输给工作人员很慢。事实上,我们发现有效载荷并没有那么大(它是 30MB)。目前一切(PHP、Gearman、节点)都在本地运行,因此网络访问不是瓶颈。
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 payload\n";
$gearmanDataString = json_encode($gearmanData, JSON_FORCE_OBJECT);
echo "Sending job to Gearman\n";
// This line takes long to execute...
$result = $client->doNormal("validateJsonSchema", $gearmanDataString);
echo "Job finished\n";
var_dump($result);
这是我的 nodejs worker,它最终会做一些事情,但它是空的,以证明 worker 代码不是问题:
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!');
});
我在后台启动我的工作人员,然后运行我的客户端,它在执行 $client->doNormal 时冻结了 30 秒左右(就在输出 向 Gearman 发送作业之后),并通过输出完成string(7) "Toasty!" 通过 PHP 的 var_dump。所以它有效,但它的处理时间很长。
另外,如果我减小有效负载 (data.json) 的大小,所需的时间会更少,因此有效负载大小似乎很重要。
我尝试用 PHP 编写相同的 worker,结果相同:
$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
});
任何线索为什么会发生这种情况? Gearman 是否可以处理这种大小的有效载荷? 30MB 在我的书中并不算大。
【问题讨论】:
-
我会做一些基本的计时调试,看看你的脚本在哪里需要很长时间。
-
@cmorrissey 我已经做过了,每次大约需要 30 秒,如果我将有效载荷减少到一半,则需要约 15 秒......所以它与有效载荷的大小直接相关,但是我不明白为什么一个不太大的有效载荷需要这么多时间才能被 gearmand 处理。
-
但是脚本中哪里需要 30 秒,它实际上是齿轮人还是
json_encode等? -
您可能需要重新考虑您的有效负载大小,因为 gearman 将整个有效负载保留在内存中。
-
您是否尝试将 $schema 和 $data 编码为 base64 或 JSON 字符串以外的其他内容?在我在 CentOS 6.6 上运行 PHP 5.3.3 的测试服务器上,似乎在 JSON 中编码 JSON 时出现问题,就像您尝试的那样。这是一个疯狂的猜测,但也许将 JSON 封装在 JSON 中会给 Gearman 带来问题?我的测试在 $data 和 $schema 中使用 base64(不到 0.1 秒)运行良好。