Skip to content
Home » PHP Gearman

PHP Gearman

What is Gearman:

  • Gearman provides a distributed application framework for work with multiple machines or processes.
  • It allows applications to complete tasks in parallel so that large tasks can be done more quickly.
  • A simple example is like a railway ticket counter where instead of having one counter(as a worker) booking multiple tickets one by one, it has multiple counters where each counter booking multiple tickets one by one so that large tasks of ticket booking can be done more quickly.

Installation:
http://gearman.org/getting-started/

How it works:

  • It has a Gearman client: Which is usually your application and is the code that sends jobs to the Gearman job server.
  • It has a worker component: Which uses the PHP Gearman worker library to register itself as handling a named job and then specifies the function name for the job.
  • Job Server(gearmand): Manage roles and rights, tracking of job runs.
    (https://launchpad.net/gearmand)
Simple code example:

Below PHP codes are based on the scenario that you want to run a particular task in parallel for all the users exist in your application.

Script for Gearman client to add task in gearman server. (client.php)

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$client= new GearmanClient();
//Add a job server to the client, can give any ip where job server to add.
$client->addServer('localhost');
//Get users
$users = getuser();
$count_user = count($users);
//For each user add a gearman job to do
foreach ($users as $user) {
//Add a background task to be run in parallel.
$task1 = $client->addTaskBackground('update_user_information', $user['userid']);
}
//Run a list of tasks in parallel.
$client->runTasks();
$client= new GearmanClient(); //Add a job server to the client, can give any ip where job server to add. $client->addServer('localhost'); //Get users $users = getuser(); $count_user = count($users); //For each user add a gearman job to do foreach ($users as $user) { //Add a background task to be run in parallel. $task1 = $client->addTaskBackground('update_user_information', $user['userid']); } //Run a list of tasks in parallel. $client->runTasks();
$client= new GearmanClient();
//Add a job server to the client, can give any ip where job server to add.
$client->addServer('localhost');

//Get users
$users = getuser();
$count_user = count($users);

//For each user add a gearman job to do
foreach ($users as $user) {
    //Add a background task to be run in parallel.
    $task1 = $client->addTaskBackground('update_user_information', $user['userid']);
}

//Run a list of tasks in parallel.
$client->runTasks();

Script for gearman worker to get the task and execute it. (worker.php)

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$worker = new GearmanWorker();
$worker->addServer('localhost');
//Register and add callback function
$worker->addFunction('update_user_information', 'call_update_user_information');
//worker will execute the task whenever it finds by running in loop waiting for jobs.
//Each time a job is received, the callback function(call_update_user_information) will run.
while (1) {
$worker->work();
}
//Below function will be called for worker when client add a task and worker receives it.
function call_update_user_information($job) {
//Write your code
//get the passed userid in the task
$userid = $job->workload();
update_user_information();
return true;
}
$worker = new GearmanWorker(); $worker->addServer('localhost'); //Register and add callback function $worker->addFunction('update_user_information', 'call_update_user_information'); //worker will execute the task whenever it finds by running in loop waiting for jobs. //Each time a job is received, the callback function(call_update_user_information) will run. while (1) { $worker->work(); } //Below function will be called for worker when client add a task and worker receives it. function call_update_user_information($job) { //Write your code //get the passed userid in the task $userid = $job->workload(); update_user_information(); return true; }
$worker = new GearmanWorker();
$worker->addServer('localhost');

//Register and add callback function
$worker->addFunction('update_user_information', 'call_update_user_information');

//worker will execute the task whenever it finds by running in loop waiting for jobs.
//Each time a job is received, the callback function(call_update_user_information) will run.
while (1) {
    $worker->work();
}

//Below function will be called for worker when client add a task and worker receives it.
function call_update_user_information($job) {
    //Write your code
    //get the passed userid in the task
    $userid = $job->workload();
    update_user_information();
    return true;
}

So suppose your application has 5 users, then when you run client.php, 5 jobs/tasks will be added to the gearman server to be done.
then you need to create multiple workers by running worker.php 5 times so that all the worker will receive the available task and process it in parallel.

You may also want to have a script to create worker dynamically based on already existing worker and total number of worker needed. (create_worker.php)

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Get number of existing workers
exec('gearadmin --workers | grep update_user_information', $running_workers, $res);
$count_workers = count($running_workers);
// Get number of existing users
$users = getuser();
$count_user = count($users);
// Number of workers to create based on number of users and number of existing workers
$needed_workers = $count_users - $count_workers;
if ($count_create_workers > 0) {
// So now you add more required worker running in the background
for ($i = 0; $i < $needed_workers; $i++) {
// Execute the worker.php script to create the worker
exec("/usr/local/bin/php worker.php > /dev/null &");
}
}
// Get number of existing workers exec('gearadmin --workers | grep update_user_information', $running_workers, $res); $count_workers = count($running_workers); // Get number of existing users $users = getuser(); $count_user = count($users); // Number of workers to create based on number of users and number of existing workers $needed_workers = $count_users - $count_workers; if ($count_create_workers > 0) { // So now you add more required worker running in the background for ($i = 0; $i < $needed_workers; $i++) { // Execute the worker.php script to create the worker exec("/usr/local/bin/php worker.php > /dev/null &"); } }
// Get number of existing workers
exec('gearadmin --workers | grep update_user_information', $running_workers, $res);
$count_workers = count($running_workers);

// Get number of existing users
$users = getuser();
$count_user = count($users);

// Number of workers to create based on number of users and number of existing workers
$needed_workers = $count_users - $count_workers;

if ($count_create_workers > 0) {
    // So now you add more required worker running in the background
    for ($i = 0; $i < $needed_workers; $i++) {
       // Execute the worker.php script to create the worker
       exec("/usr/local/bin/php worker.php > /dev/null &");
    }
}

Few useful commands:
Clear job queue:

gearman -n -w -f update_user_information > /dev/null
gearman -n -w -f update_user_information > /dev/null
Drop any function:
gearadmin --drop-function update_user_information
gearadmin --drop-function update_user_information
Get workers:
gearadmin --workers | grep update_user_information
gearadmin --workers | grep update_user_information

To kill any worker:
First, find the worker using

ps -ef | grep create_worker.php
ps -ef | grep create_worker.php
Then kill the worker using
kill process_id_of_worker_from_above
kill process_id_of_worker_from_above

Gearman-UI: (To monitor – Function, Server, Queued jobs, Running jobs, Available workers)
https://github.com/gaspaio/gearmanui

More at http://gearman.org/manual/

1 thought on “PHP Gearman”

Leave a Reply

Your email address will not be published. Required fields are marked *