This example is to query several result sets from the database. The general practice is to send queries one by one and then summarize the results for output.
The following describes how to use gearman_client_run_tasks of gearman to implement concurrent queries. The gearman_client_run_tasks interface can submit multiple tasks at a time and then asynchronously process the results in the callback function.
The ratio of PHP is as follows:
The client:
<?php$client = new GearmanClient();$client->addServer();// initialize the results of our 3 "query results" here$userInfo = $friends = $posts = null;// This sets up what gearman will callback to as tasks are returned to us.// The $context helps us know which function is being returned so we can // handle it correctly.$client->setCompleteCallback(function(GearmanTask $task, $context) use (&$userInfo, &$friends, &$posts) { switch($context) { case 'lookup_user': $userInfo = $task->data(); break; case 'baconate': $friends = $task->data(); break; case 'get_latest_posts_by': $posts = $task->data(); break; }});// Here we queue up multiple tasks to be execute in *as much* parallelism as gearmand can give us$client->addTask('lookup_user', '[email protected]', 'lookup_user');$client->addTask('baconate', '[email protected]', 'baconate');$client->addTask('get_latest_posts_by', '[email protected]', 'get_latest_posts_by');echo "Fetching...\n";$start = microtime(true);$client->runTasks();$totaltime = number_format(microtime(true) - $start, 2);echo "Got user info in: $totaltime seconds:\n";var_dump($userInfo, $friends, $posts);
The worker:
<?php$worker = new GearmanWorker();$worker->addServer();$worker->addFunction('lookup_user', function(GearmanJob $job){ // normally you'd so some very safe type checking and query binding to a database here. // ...and we're gonna fake that. sleep(3); return 'The user requested ('. $job->workload() .') is 7 feet tall and awesome';});$worker->addFunction('baconate', function(GearmanJob $job){ sleep(3); return 'The user ('. $job->workload() .') is 1 degree away from Kevin Bacon';});$worker->addFunction('get_latest_posts_by', function(GearmanJob $job){ sleep(3); return 'The user ('. $job->workload() .') has no posts, sorry!';});while ($worker->work());
Execution result:
Fetching...Got user info in: 9.00 seconds:string(59) "The user requested ([email protected]) is 7 feet tall and awesome"string(56) "The user ([email protected]) is 1 degree away from Kevin Bacon"string(43) "The user ([email protected]) has no posts, sorry!"</span>
It still takes 9 s to discover, because there is only one worker which can only be run in sequence.
Execute three workers or many other workers together. Try again:
Fetching...Got user info in: 3.00 seconds:string(59) "The user requested ([email protected]) is 7 feet tall and awesome"string(56) "The user ([email protected]) is 1 degree away from Kevin Bacon"string(43) "The user ([email protected]) has no posts, sorry!"</span>
This is just an example of parallel operation. It can have better concurrency performance in practical applications.
Use gearman to implement multi-Query)