gearman的安裝與使用

Gearman是一個分發任務的程序框架,它會對做業進行排隊自動分配到一系列機器上。gearman跨語言跨平臺,很方便的實現異步後臺任務。php官方收錄:http://php.net/manual/zh/book.gearman.phpphp

 

2、安裝

一、安裝服務器端:

官方下載,請到https://launchpad.net/gearmandlinux

yum install boost-devel* gperf* libevent-devel* libuuid-devel
wget https://launchpad.net/gearmand/1.2/1.1.12/+download/gearmand-1.1.12.tar.gz
tar zxvf gearmand…
cd gearmand …
./configure
make && make installc++

安裝該擴展須要先安裝一些依賴,建議直接默認./configure,不要指定路徑等。shell

常見問題1:提示找不到boost>=1.39,明明已經安裝了,這裏應該是沒有安裝gcc-c++,有的機器有gcc卻不必定帶有gcc-c++。yum install gcc-c++應該就能夠了。apache

常見問題2:安裝完成後啓動不成功,gearmand -d或者gearmand -d -u root都啓動不起來。gearmand -vvv調試模式卻提示未定義選項-v。這時應該是觸發gearmand新版本的bug了,查看log應該能看到「000000 [  main ] socket()(Address family not supported by protocol) -> libgearman-server/gearmand.cc:470」這個錯誤,解決辦法是啓動時添加參數-L 0.0.0.0,限定只綁定ipv4地址,忽略ipv6。或者安裝不高於1.0.2的版本。參見官方反饋帖子:https://bugs.launchpad.net/gearmand/+bug/1134534json

參考連接:http://www.usamurai.com/2013/05/01/install-gearman-from-source-in-centos/centos

二、安裝gearman的php擴展

下載擴展程序:http://pecl.php.net/package/gearmanbash

wget http://pecl.php.net/get/gearman-1.1.2.tgz
tar zxvf gearman-1….
cd gearman-1 …
phpize
./configure
make && make install服務器

很快就安裝完成,最後會展現so文件的路徑,如: /usr/lib64/php/modules/框架

在php.ini末尾加上extension=」/usr/lib64/php/modules/gearman.so」,重啓apache,輸出php –info |grep 「gearman」或者php -m或者網頁輸出phpinfo()都能看到已經安裝成功。

常見問題:configure時若是提示找不到php-config,請指定。如–with-php-config=/usr/local/php/bin/php-config,注意要指定完整,不要只寫目錄。

 

 

3、實例

client:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
$client=newGearmanClient();
$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有效
functioncompleteCallBack($task)
{
    echo'CompleteCallback!handle result:'.$task->data().'<br/>';
}

worker:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
$worker=newGearmanWorker();
$worker->addServer();
$worker->addFunction('say',function(GearmanJob$job){
    $workload=$job->workload();//接收client傳遞的數據
    echo'receive data:'.$workload.PHP_EOL;
    returnstrrev($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

4、pcntl擴展實現粗略的多worker守護

因爲worker要長駐後臺時刻準備着被jobserver調用來處理job,因此worker不能死掉,網上有的解決辦法是經過定時任務進行重啓 worker,這應該是不錯的方案。也有說進行多進程守護,但實際上php比較難實現,經過pcntl擴展是其中一種方案,主進程forck出來的子進程 來啓動運行worker,至關於worker做爲主進程的子進程。主進程監護着子進程,worker死掉及時啓動新的一個。但若是主進程死掉呢?因爲主進 程不進行什麼業務處理,死掉的機率要比子進程worker死掉的機率要小很多吧。

 

 

5、linux直接運行 (這樣能夠防止php端運行時php掛掉沒法執行)

能夠如今咱們的php中先寫一個類:好比wxPushMsg.class  而後咱們去調用它 

/*get data by gearman*/
$data = file_get_contents('php://stdin');//接收gearman 傳遞過來的data
$data = json_decode($data, true);
$send_data = $data['data'];
$send_tmp = $data['tmp_id'];
$send_test = $data['test'];
WxPubMsg::send_batch($send_data, $send_tmp, $send_test);

控制器端調用gearman Task
$client=newGearmanClient();
$client->addServer();//本機能夠直接addServer(),默認服務器端使用4730端口
$client->addTask('wx_push',json_encode($push_data));//
$client->runTasks();//運行隊列中的任務,只是do系列不須要runTask()。

而後咱們linux運行wxPushMsg ;
 gearman -w -f wx_push -N /home/wwwroot/domain/modules/distr/modules/classes/wxPushMsg.class.php > /dev/null 2>&1 &
 linux端查看gearman運行workes  gearman --workers
 
啓動:/usr/local/sbin/gearmand -d -l /var/log/gman/gm.log
或者:gearmand -L 127.0.0.1 -p 4730 -u root -d
 
shell腳本:

#!/bin/bash
#this is for gearman worker
#@author FLY
#2016-11-08 PM
# ./gmworker.sh gmname xxx.php cmd(status,start,stop,retart)
if [ "$#" -ge 3 ]
then
echo "ready to go"
echo "name:"$1
echo "file:"$2
echo "cmd:"$3 #start ,stop,restart
else
echo "err:need 3 arguments!"
exit
fi
gname=$1
gflie=$2
cmd=$3
#start
function stratr_worker(){
name=$1
file=$2
script=$(cd `dirname $0`; pwd)'/'$file
echo "path:"$script
echo "cmd:gearman -w -f "$name" -N $script >/dev/null 2>&1 &"
eval "gearman -w -f "$name" -N $script >/dev/null 2>&1 &"
}
#kill pro
function stop_worker(){
name=$1
file=$2
declare -a list=($(ps -ef|grep "$name"|awk '{print $2}'))

for pid in "${list[@]}"
do
eval "kill -9 $pid"
# echo "kill -9 $pid"
done
#eval "for pid in ; do kill -9 $pid; done"
}
#get status
function status_worker(){
name=$1
declare -a list=($(ps -ef|grep "$name"|awk '{print $2 }'))
for worker in "${list[@]}"
do
echo "-----------------------------------------"
echo "pid:$worker `cat /proc/$worker/cmdline`"
done
}
#cmd exec
case $cmd in
"start")
stratr_worker $gname $gflie
;;
"stop")
stop_worker $gname $gfile
;;
"restart")
stop_worker $gname $gfile
stratr_worker $gname $gfile
;;
"status")
status_worker $gname $gfile
;;
*)
echo "cmd [$cmd] wrong, do nothing!"
;;
esac

 

 跨服務器使用: 

gearman -h 服務器ip -w -f task_name -N gm_worker_file_path 

 
一、若是出現錯誤,能夠在configure時指定"--with-gearman=",讓php找到適合的libgearman 二、若是出現"[php_gearman.lo] Error 1"錯誤, 能夠將"php_gearman.loT" 拷貝一個 "php_gearman.lo",而後再make 三、若是啓動php的時候gearman.so無效,則gearman擴展版本要到1.1.0版本才行
相關文章
相關標籤/搜索