zoukankan      html  css  js  c++  java
  • gearman的安装与使用

    Gearman是一个分发任务的程序框架,它会对作业进行排队自动分配到一系列机器上。gearman跨语言跨平台,很方便的实现异步后台任务。php官方收录:http://php.net/manual/zh/book.gearman.php

    二、安装

    1、安装服务器端:

    官方下载,请到https://launchpad.net/gearmand

    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 install

    安装该扩展需要先安装一些依赖,建议直接默认./configure,不要指定路径等。

    常见问题1:提示找不到boost>=1.39,明明已经安装了,这里应该是没有安装gcc-c++,有的机器有gcc却不一定带有gcc-c++。yum install gcc-c++应该就可以了。

    常见问题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/1134534

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

    2、安装gearman的php扩展

    下载扩展程序:http://pecl.php.net/package/gearman

    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,注意要指定完整,不要只写目录。

    三、实例

    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

    四、pcntl扩展实现粗略的多worker守护

    由于worker要长驻后台时刻准备着被jobserver调用来处理job,所以worker不能死掉,网上有的解决办法是通过定时任务进行重启 worker,这应该是不错的方案。也有说进行多进程守护,但实际上php比较难实现,通过pcntl扩展是其中一种方案,主进程forck出来的子进程 来启动运行worker,相当于worker作为主进程的子进程。主进程监护着子进程,worker死掉及时启动新的一个。但如果主进程死掉呢?由于主进 程不进行什么业务处理,死掉的概率要比子进程worker死掉的概率要小不少吧。

    五、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 

     
    1、如果出现错误,可以在configure时指定"--with-gearman=",让php找到适合的libgearman
    2、如果出现"[php_gearman.lo] Error 1"错误, 可以将"php_gearman.loT" 拷贝一个 "php_gearman.lo",然后再make
    3、如果启动php的时候gearman.so无效,则gearman扩展版本要到1.1.0版本才行
  • 相关阅读:
    【Java EE 学习 36】【struts2】【struts2系统验证】【struts2 ognl值栈】【struts2 ongl标签】【struts2 UI标签】【struts2模型驱动和令牌机制】
    【Java EE 学习 35 下】【struts2】【struts2文件上传】【struts2自定义拦截器】【struts2手动验证】
    【Java EE 学习 35 上】【strus2】【类型转换器】【struts2和Servlet API解耦】【国际化问题】【资源文件乱码问题已经解决】
    【Java EE 学习 34】【struts2学习第一天】
    【JavaScript中的正则表达式】
    【Java EE 学习 33 下】【validate表单验证插件】
    【Java EE 学习 33 上】【JQuery样式操作】【JQuery中的Ajax操作】【JQuery中的XML操作】
    【Java EE 学习 32 下】【JQuery】【JQuey中的DOM操作】
    【Java EE 学习 32 上】【JQuery】【选择器】
    【Java EE 学习 31】【JavaScript基础增强】【Ajax基础】【Json基础】
  • 原文地址:https://www.cnblogs.com/ruanqin/p/5983660.html
Copyright © 2011-2022 走看看