Подтвердить что ты не робот

Gearman медленно, когда клиент отправляет большую полезную нагрузку

У меня есть проблема с использованием Gearman, которая медленно переносит задачи на работников, когда я отправляю ей большие полезные нагрузки через расширение PHP Gearman. На самом деле мы не находим полезную нагрузку такой большой (она 30 МБ). Все (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 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, который в конечном итоге что-то сделает, но пуст, чтобы продемонстрировать, что рабочий код не является проблемой:

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) и заканчивает вывод string(7) "Toasty!" через PHP var_dump. Так оно и работает, но его просто нужно обработать.

Кроме того, если я уменьшаю размер полезной нагрузки (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!';
}

UPDATE

Используя клиент 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 не так уж и много в моей книге.

4b9b3361

Ответ 1

Проверьте, работает ли этот код для вас, заняло очень мало времени, чтобы завершить работу.

worker.php:

echo "Starting\n";
$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 finished\n";

$endtime = time();
print "Completed in " . ($endtime - $time) . ' seconds' . "\n";

function complete($task)
{
    print "Unique : " . $task->unique() . "\n";
    print "Data : " . $task->data() . "\n";
}

Я использовал методы addTask и runTasks вместо doNormal. Для отправки json-данных я использовал файл AllSets.json из http://mtgjson.com/ около 30 МБ (общая нагрузка), задание завершено в 1 секунду, а после попытки файла размером около 200 Мб потребовалось 4 секунды.