在我之前的文章中,介绍过Gearman的使用。在我的项目中,我使用了PHP来编写一直运行的Worker。如果按照Gearman官方推荐的例子,只是简单的一个循环来等待任务,会有一些问题,包括:1、当代码进行过修改之后,如何让代码的修改生效;2、重启Worker的时候,如何保证当前的任务处理完成才重启。
 
针对这个问题,我考虑了以下的解决方法:
1、每次修改完代码后,Worker需要手工重启(先杀死然后启动)。这个只能解决重新加载配置文件的问题。
2、在Worker中设置,单次任务循环完成后,就对Worker进行重启。这个方案的问题在于消耗比较大。
3、在Worker中添加一个退出函数,如果需要Worker退出的时候,在Client端发送一个优先级比较高的退出调用。这个需要客户端配合,在使用后台类任务时,不太适合。
4、在Worker中检查文件是否发生变化,如果发生了变化,退出并重启自身。
5、为Worker编写信号控制,接受重启指令,类似于 http restart graceful 指令。
 
最后,结合4和5两种方法,可以实现这样一个Daemon,如果配置文件发生了变化,他就会自动重启;如果接受到了用户的 kill  -1 pid 信号,也会重新启动。
 
代码如下:
 
<?php

declare( ticks = 1 );

// This case will check the config file regularly, if the config file changed, it will restart it self

// If you want to restart the daemon gracefully, give it a HUP signal

// by shiqiang<cocowool@gmail.com> at 2011-12-04

$init_md5 = md5_file( 'config.php');

// register signal handler

pcntl_signal( SIGALRM, "signal_handler", true );

pcntl_signal( SIGHUP, 'signal_handler', TRUE );

$job_flag = FALSE;    //Job status flag, to justify if the job has been finished

$signal_flag = FALSE;    //Signal status flag, to justify whether we received the kill -1 signal

while( 1 ){

    $job_flag = FALSE;    //Job status flag

    print "Worker start running ... \n";

    sleep(5);

    print "Worker's task done ... \n";

    $flag = TRUE;    //Job status flag

    AutoStart( $signal_flag );

}

function signal_handler( $signal ) {

    global $job_flag;

    global $signal_flag;

    switch( $signal ){

        case SIGQUIT:

            print date('y-m-d H:i:s', time() ) . " Caught Signal : SIGQUIT - No : $signal \n";

            exit(0);

            break;

        case SIGSTOP:

            print date('y-m-d H:i:s', time() ) . " Caught Signal : SIGSTOP - No : $signal \n";

            break;

        case SIGHUP:

            print date('y-m-d H:i:s', time() ) . " Caught Signal : SIGHUP - No : $signal \n";

            if( $flag === TRUE ){

                AutoStart( TRUE );

            }else{

                $signal_flag = TRUE;

            }

            break;

        case SIGALRM:

            print date('y-m-d H:i:s', time() ) . " Caught Signal : SIGALRM - No : $signal \n";

            //pcntl_exec( '/bin/ls' );

            pcntl_alarm( 5 );

            break;

        default:

            break;

    }

}

function AutoStart( $signal = FALSE, $filename = 'config.php' ){

    global $init_md5;

    if( $signal || md5_file( $filename ) != $init_md5 ){

        print "The config file has been changed, we are going to restart. \n";

        $pid = pcntl_fork();

        if( $pid == -1 ){

            print "Fork error \n";

        }else if( $pid > 0 ){

            print "Parent exit \n";

            exit(0);

        }else{

            $init_md5 = md5_file( $filename );

            print "Child continue to run \n";

        }

    }

}

  

参考资料:
 
再参考一下下面的片段:
 
<?php

function handle_http_request($address, $port){
$max_backlog = 16;
$res_content = "HTTP/1.1 200 OK \n".
"Content-Length: 15 \n".
"Content-Type: text/plain; charset=UTF-8 \n".
"PHP HTTP Server Hello World!!";
$res_len = strlen($res_content); //Create, bind and listen to socket
if(($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === FALSE){
echo "Create socket failed!\n";
exit;
} if((socket_bind($socket, $address, $port)) === FALSE)
{
echo "Bind socket failed!\n";
exit;
} if((socket_listen($socket, $max_backlog)) === FALSE)
{
echo "Listen to socket failed!\n";
exit;
} //loop
while (true) {
if( ($accept_socket = socket_accept($socket)) === FALSE ){
continue;
}else{
socket_write($accept_socket, $res_content, $res_len);
socket_close($accept_socket);
}
} } //Run as daemon process.
function run(){ if(($pid1 = pcntl_fork()) === 0){ posix_setsid();//Set first child process as the session leader. if(($pid2 = pcntl_fork()) === 0){
handle_http_request('192.168.255.131', 10101);
}else{
exit;
}
}else{
pcntl_wait($status);
}
} run();
?>

  

[Linux]使用PHP编写Gearman的Worker守护进程的更多相关文章

  1. Linux Rsync备份服务介绍及部署守护进程模式

    rsync介绍 rsync是一款开源的.快速的.多功能的.可实现全量及增量的本地或远程数据同步备份工具 在常驻模式(daemon mode)下,rsync默认监听TCP端口873,以原生rsync传输 ...

  2. linux分享六:nohup与&,守护进程

    contab每秒执行脚本,然后将把标准错误重定向到标准输出(2>&1)以追加的方式写入log_cronjob.txt.补充:试想2>1代表什么,2与>结合代表错误重定向,而1 ...

  3. linux下为.net core应用创建守护进程

    1.Supervisor 安装 yum install python-setuptools easy_install supervisor 2.配置 Supervisor mkdir /etc/sup ...

  4. 编写Linux/Unix守护进程

    原文: http://www.cnblogs.com/haimingwey/archive/2012/04/25/2470190.html 守护进程在Linux/Unix系统中有着广泛的应用.有时,开 ...

  5. linux系统编程之进程(八):守护进程详解及创建,daemon()使用

    一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.它不需要用户输入就能运行而且提供某种服务,不是对整个 ...

  6. 创建守护进程步骤与setsid() -- linux deamon进程

    原创:http://www.cnblogs.com/mickole/p/3188321.html 一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终端并且 ...

  7. Linux 下Qt实现守护进程实例(转)

     原文地址:Linux守护进程的编程方法(含实例) 作者:lingdxuyan 参考文献 Linux信号列表(zz) Linux 守护进程的编程方法 linux上编写守护进程的例程 Linux下后台守 ...

  8. Linux系统编程之--守护进程的创建和详解【转】

    本文转载自:http://www.cnblogs.com/mickole/p/3188321.html 一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终 ...

  9. linux系统编程:守护进程详解及创建,daemon()使用

    一,守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.它不需要用户输入就能运行而且提供某种服务,不是对整个 ...

随机推荐

  1. JSP基础学习

    JQuery教程: http://www.w3school.com.cn/jquery/ HTTP协议的 http://www.w3.org/Protocols/rfc2616/rfc2616.htm ...

  2. php 异常处理类

    PHP具有很多异常处理类,其中Exception是所有异常处理的基类. Exception具有几个基本属性与方法,其中包括了: message 异常消息内容code 异常代码file 抛出异常的文件名 ...

  3. 初次尝试用Kotlin实现Android项目

    Kotlin: The Swift of Android 起这个文内标题的原因很简单,就是对Kotlin抱有希望--能使Android的开发更简洁.高效及安全.知道Kotlin是从简书的一篇短文,越来 ...

  4. SQL联合查询(内联、左联、右联、全联)的语法(转)

    最近在做一个比较复杂的业务,涉及的表较多,于是在网上找了一些sql联合查询的例子进行研究使用. 概述: 联合查询效率较高,举例子来说明联合查询:内联inner join .左联left outer j ...

  5. python使用uuid库生成唯一id

    概述: UUID是128位的全局唯一标识符,通常由32字节的字符串表示. 它可以保证时间和空间的唯一性,也称为GUID,全称为: UUID -- Universally Unique IDentifi ...

  6. 微信跳转浏览器来下载不同系统的app

    在微信里面,是不能通过应用宝以外的方式去直接下载app的,但是却可以通过跳转到浏览器去下载app,因此如果刚好各位公司有刚刚上线的app,来不及放到微信应用宝那里,可以试试这种办法. 实现思路: 1. ...

  7. C# 在类中反射

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Wind ...

  8. Xcode6 管理provisioning profile

    profile文件的存放位置为 /Users/用户名/Library/MobileDevice/Provisioning Profiles 更新profile文件后,Code Signing Iden ...

  9. php网址显示excel表格内容

    /** * excel表格内容在网页中显示 * * 首先需要下载PHPExcel 工具包 * 网址: http://phpexcel.codeplex.com/releases/view/119187 ...

  10. 深入浅出HTTP请求(转自http://www.cnblogs.com/yin-jingyu/archive/2011/08/01/2123548.html)

    HTTP(HyperText Transfer Protocol)是一套计算机通过网络进行通信的规则.计算机专家设计出HTTP,使HTTP客户(如Web浏览器)能够从HTTP服务器(Web服务 器)请 ...