2015-08-06 9 views
23

Ich habe ein Problem mit Gearman, die langsam Aufgaben an Mitarbeiter übertragen, wenn ich es große Nutzlasten über die Gearman PHP-Erweiterung senden. Tatsächlich finden wir die Nutzlast nicht so groß (30 MB). Alles (PHP, Gearman, Node) läuft vor Ort, daher ist der Netzwerkzugriff nicht der Flaschenhals.Gearman langsam, wenn Client große Nutzlast sendet

Das PHP-Script

Hier ist der Kunde 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); 

Das ist mein NodeJS Arbeiter, die schließlich etwas tun, aber leer ist, dass Arbeiter Code zu demonstrieren ist kein Thema:

Ich beginne meinen Arbeiter im Hintergrund und dann meinen Klienten laufen, und es friert während 30 Sekunden oder so während $client->doNormal (gerade nach outputi ng Senden Job an Gearman), und endet durch Ausgabe string(7) "Toasty!" über PHP var_dump. So funktioniert es, aber es ist einfach lange zu verarbeiten.

Auch wenn ich die Größe der Nutzlast (data.json) reduzieren, dauert es weniger Zeit, so dass die Nutzlast Größe wichtig scheint.

Ich habe versucht, den gleichen Arbeiter in PHP, mit dem gleichen Ergebnis zu kodieren:

$worker= new GearmanWorker(); 
$worker->addServer('127.0.0.1', '4730'); 
$worker->addFunction("validateJsonSchema", "validateJsonSchema"); 
while ($worker->work()); 

function validateJsonSchema($job) 
{ 
    return 'ToastyPHP!'; 
} 

UPDATE

den node.js Client, fast das gleiche tun als in PHP, es führt viel schneller aus (~ 3,5 Sekunden). Mache ich etwas falsch mit der PHP-Version, oder fehlt mir eine Konfiguration, um es schneller zu machen?

Mein node.js Client:

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 
}); 

Jede Ahnung, warum ist das passiert? Ist Gearman auf diese Nutzlast ausgelegt? 30MB ist nicht so groß in meinem Buch.

+0

Ich würde einige grundlegende Timing-Debugging tun, um zu sehen, wo in Ihrem Skript dauert es eine lange Zeit. – cmorrissey

+0

@cmorrissey Ich habe bereits, dauert ~ 30 Sekunden jedes Mal, wenn ich die Nutzlast auf die Hälfte der Größe verringern, dauert es ~ 15 Sekunden ... so ist es direkt mit der Größe der Nutzlast verbunden, aber ich verstehe nicht, warum a nicht so große Nutzlast braucht so viel Zeit, um mit dem Getriebe fertig zu werden. – MaxiWheat

+0

aber wo in dem Skript dauert es 30 Sekunden, ist es tatsächlich gearman oder ist es 'json_encode', etc? – cmorrissey

Antwort

1

Überprüfen Sie, ob dieser Code für Sie funktioniert, nahm wirklich wenig Zeit, um den Job abzuschließen.

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"; 
} 

ich die addTask und runTasks Methoden verwendet haben, statt doNormal.For die JSON-Daten zu senden habe ich Die AllSets.json Datei von http://mtgjson.com/ um 30MB Größe (Gesamtlast), der Job in 1 Sek. abgeschlossen, und nach dem Versuch, eine Datei von rund 200MB dauerte es 4 Sek.