gearman及安装,php使用
Gearman是一个用来把工作委派给其他机器、分布式的调用更适合做某项工作的机器、并发的做某项工作在多个调用间做负载均衡、或用来在调用其它语言的函数的系统。
通常,多语言多系统之间的集成是个大问题,一般来说,人们多半会采用 WebService 的方式来处理此类集成问题,但不管采用何种风格的 WebService,如 RPC 风格,或者 REST 风格,其本身都有一定的复杂性。相比之下,Gearman 也能实现类似的作用,而且更简单易用。
可实现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;
- }
发表评论: