gearman及安装,php使用

Gearman是一个用来把工作委派给其他机器、分布式的调用更适合做某项工作的机器、并发的做某项工作在多个调用间做负载均衡、或用来在调用其它语言的函数的系统。

通常,多语言多系统之间的集成是个大问题,一般来说,人们多半会采用 WebService 的方式来处理此类集成问题,但不管采用何种风格的 WebService,如 RPC 风格,或者 REST 风格,其本身都有一定的复杂性。相比之下,Gearman 也能实现类似的作用,而且更简单易用。

cluster.png

可实现php与java互相通信。


一、server安装

下载 server,官方网站上提供了三个语言版本的server。http://gearman.org/download/

我们选择C语言版本,下载地址为,https://launchpad.net/gearmand

目前提供下载的是gearmand-1.1.12.tar.gz。

在编译之前,需要先安装用到的库问题,

(1)yum install boost-devel -y

(2)yum install gprep -y

(3)yum install libevent-devel -y

(4)yum install libuuid-devel -y

解压gearmand-1.1.12,执行

 

./configure make make install

安装完成后,在命令行运行,就可以在本地就启动一个Job server ,等待client 和worker 连接。

 

gearmand -d

二、安装PHP扩展


1、gearman

利用pecl安装gearman php扩展。建议在安装gearman server的时候采用默认安装,这样在安装php 扩展的时候就比较容易找到需要的头文件、链接文件。

pecl install gearman

编辑php.ini,添加

extension="gearman.so"

命令行测试 php -m |grep gearman


client:

<?php
$client = new GearmanClient();
$client->addServer('127.0.0.1', 4730);//本机可以直接addServer(),默认服务器端使用4730端口
$client->setCompleteCallback('completeCallBack');//先绑定才有效
 
$result1 = $client->do('say', 'do');//do是同步进行,进行处理并返回处理结果。
$result2 = $client->doBackground('say', 'doBackground');//异步进行,只返回处理句柄。
$result3 = $client->addTask('say', 'addTask');//添加任务到队列,同步进行?通过添加task可以设置回调函数。
$result4 = $client->addTaskBackground('say', 'addTaskBackground');//添加后台任务到队列,异步进行?
$client->runTasks();//运行队列中的任务,只是do系列不需要runTask()。
 
echo 'result1:';
var_dump($result1);
echo '<br/>';
 
echo 'result2:';
var_dump($result2);
echo '<br/>';
 
echo 'result3:';
var_dump($result3);
echo '<br/>';
 
echo 'result4:';
var_dump($result4);
echo '<br/>';
 
//绑定回调函数,只对addTask有效
function completeCallBack($task)
{
    echo 'CompleteCallback!handle result:'.$task->data().'<br/>';
}




worker:

<?php
$worker = new GearmanWorker();
$worker->addServer();
$worker->addFunction('say', function(GearmanJob $job){
    $workload = $job->workload();//接收client传递的数据
    echo 'receive data:'.$workload.PHP_EOL;
    return strrev($workload);//仅作反转处理
});
 
//无际循环运行,gearman内部已有处理,不会出现占用过高死掉的情况
while($worker->work()){
    if($worker->returnCode() !== GEARMAN_SUCCESS){
        echo 'error'.PHP_EOL;
    }
}

以上client输出:

CompleteCallback!handle result:ksaTdda
result1:string(2) “od”
result2:string(17) “H:iZ943bixttyZ:87”
result3:object(GearmanTask)#2 (0) { }
result4:object(GearmanTask)#3 (0) { }

worker输出:

receive data:do
receive data:doBackground
receive data:addTaskBackground
receive data:addTask


2、net_gearman

https://github.com/andreybolonin/Net_Gearman

http://pear.php.net/package/Net_Gearman

pear install Net_Gearman


clien端主要代码:

// 一个client对象,需要jobserver信息,一个数组 

$client = new Net_Gearman_Client (gm::$servers); 

// Example1就是function name 

$client->Example1 (array ('date'));


worker端主要代码:

// worker对象,需要jobserver信息 

$worker = new Net_Gearman_Worker (gm::$servers); 

// 传入function name,给他处理Example1的能力 

$worker->addAbility ('Example1'); 

// loop 

$worker->beginWork ();



和传统的gearman api略有差别,Net_Geaman需要用户以子类形式实现function,例如Example1.php文件代码片段:


	

class Net_Gearman_Job_Example1 extends Net_Gearman_Job_Common

{

// arg 是数组,与client里面的入参array对应

public function run ($arg)

{

$cmd = $arg[0];

//...

return $result;

}

}

client侧引入task和set概念,这样就可以累加多个任务到一个集合,一起发出,client片段:

$set = new Net_Gearman_Set();

$task = new Net_Gearman_Task ('Example1', array ('date'));

$set->addTask ($task);

$client->runSet ($set);

例子3:  增加了完成任务后的回调功能,回调的参数有function name,句柄(包好jobserver:number,主要是唯一标识一下这次任务),还有任务的返回值。

$task->attachCallback ("complete",Net_Gearman_Task::TASK_COMPLETE);
//... function complete ($func, $handle, $result) {
    gm::log_msg ("[gm_client] complete ($handle/$func)");
    gm::log_msg ("[gm_client] result: " . $result['result']);
}

例子4: 
主要是展示通过complete回调回传数据。 
例子5: 
展示client端添加fail回调,当function中抛出Net_Gearman_Job_Exception异常时候,会触发 fail类型的回调,代码片段:

	

class Net_Gearman_Job_Example3 extends Net_Gearman_Job_Common {

public function run ($arg) { if (count ($arg) != 1)

{

throw new Net_Gearman_Job_Exception ("must provide exactly one command to run");

} //...
  • $task->attachCallback ("complete",Net_Gearman_Task::TASK_COMPLETE);
  • $task->attachCallback ("fail",Net_Gearman_Task::TASK_FAIL);
  • //...
  • function fail ($task) {
  • gm::log_msg ("[gm_client] fail, task: " . print_r ($task, true));
  • }

但异常内容并不会回传给fail回调函数,所以还是建议使用正常的complete回调,用户可以自己捕获失败信息放到返回值里面。 
例子6: 
worker里面使用了monitor功能,代码片段:

	

$worker->beginWork ('monitor');

// ...

function monitor ($idle, $time_of_last_job) {

$idle_str = ($idle) ? 'idle' : 'not idle';

$time_of_last_job_str = date ('r', $time_of_last_job);

gm::log_msg ("[gm_worker] status: $idle_str, time of last job: $time_of_last_job_str"); }
  • 其触发事件有: 
  • job开始前。 
  • job完成后。 
  • 等待job时候,一分钟触发一次。
  • 例子7: 
  • 主要是在worker端添加了任务的start,complete和fail回调,可以在里面做点事情,代码片段:
  • $worker->attachCallback ('job_start', Net_Gearman_Worker::JOB_START);
  • $worker->attachCallback ('job_complete', Net_Gearman_Worker::JOB_COMPLETE);
  • $worker->attachCallback ('job_fail', Net_Gearman_Worker::JOB_FAIL);
	
  • 例子8: 
  • 是一个大综合,主要有以下几点值得注意: 
  • 1. 作者虽然很喜欢php,但也认为让php承担一个daemon的worker不是很保险的事情,可能涉及异常退出啊、内存使用不合理呀什么的,有可能影响性能,所以他提供了一个策略:每个worker有个实例编号,使用文件锁来确保一个实例编号只有一个worker运行,worker在处理了一定数目的job后自动退出,使用crontab任务秒级拉起worker。 
  • 2. worker的beginWorker退出可以在monitor回调中判断,monitor回调有这种特性:回调函数返回false则worker继续loop,返回true则loop退出,这个在worker的源码中也得到证实:
  • if (call_user_func($monitor, $idle, $lastJob) == true) {
  • $working = false;
  • }



标签: php gearman
2017.4.6   /   热度:1866   /   分类: php

发表评论:

©地球仪的BLOG  |  Powered by Emlog