php 守护进程

作者: aoshi | 来源:发表于2017-12-15 17:38 被阅读86次
php扩展需求
php-pcntl
php-posix
守护进程实现代码
Class Daemon{

    /**
     * 初始化一个守护进程
     * @throws Exception
     */
    public function init(){
        //创建一个子进程
        $pid = pcntl_fork();

        if ($pid == -1) {
            throw new Exception('fork子进程失败');
        } elseif ($pid > 0) {
            //父进程退出,子进程变成孤儿进程被1号进程收养,进程脱离终端
            exit(0);
        }

        //创建一个新的会话,脱离终端控制,更改子进程为组长进程
        $sid = posix_setsid();
        if ($sid == -1) {
            throw new Exception('setsid fail');
        }

        //修改当前进程的工作目录,由于子进程会继承父进程的工作目录,修改工作目录以释放对父进程工作目录的占用。
        chdir('/');

        /**
         * 通过上一步,我们创建了一个新的会话组长,进程组长,且脱离了终端,但是会话组长可以申请重新打开一个终端,为了避免
         * 这种情况,我们再次创建一个子进程,并退出当前进程,这样运行的进程就不再是会话组长。
         */
        $pid = pcntl_fork();
        if ($pid == -1) {
            throw new Exception('fork子进程失败');
        } elseif ($pid > 0) {
            //再一次退出父进程,子进程成为最终的守护进程
            exit(0);
        }
        //由于守护进程用不到标准输入输出,关闭标准输入,输出,错误输出描述符
        fclose(STDIN);
        fclose(STDOUT);
        fclose(STDERR);
    }
}

实例化一个守护进程
$daemon = new Daemon();
$daemon->init();
针对需求进行分析:

需求:有一个常驻队列messageQueue(假设在redis内存中),这个队列会有可能有请求不定期的往队列中增加元素。同时我们要求在队列中有元素的时候,按照队列顺序将元素pop出来,并进行处理(假设这个处理只是echo ‘test’);

解决方法:

现在假设已经有了两个函数

function oPopMessageQueue(){ …} //获取队列最后一个元素;

function vDealElement($element) { …} 处理元素;

要求写出一个守护程序,完成上面的需求。

好了,这个程序很容易想到,可以使用while循环来做

程序:
while(true)
{
    if( $element  = oPopMessageQueue())
    {
        vDealElement($element);
    }   
}
考虑1 : 这个程序如果一直跑的话已经可以满足上面的需求了.

但是考虑到:1 用php进程跑有可能会由于各种情况(比如运行时间过长),Cpu使用率达到100%,进程挂了,这样程序就无法自动重连了.

方法:使用cron

我们在定时脚本中每10分钟起一个进程跑这个程序。

然后设置这个程序的运行时间为10分钟,10分钟后自动取消,于是代码变成

$timeStart = time();        //设置开始值
while(true) {
    //有设置开始值
    if(empty($timeStart)) {
        $timeStart = time();
    }

    $diffTime = time() - $timeStart;      //计算进程时间差
    if($diffTime > 600) {     //时间超过5秒
        exit;       //终止运行
    }
}
考虑2,可能会有这种需求: 需要有随时让脚本暂停的功能:
于是考虑使用文件或者缓存来增加暂停功能

方法1:  让程序终止执行,有需要的时候再次启动进程
while(true) {
    if(file_exists("/home/daemon/stop"))    //判断终止文件是否存在
    {
        exit;
    }
}

方法2:让程序睡眠指定秒数
while(true) {
    if(file_exists("/home/daemon/sleep"))    //判断终止文件是否存在
    {
        $second = file_get_contents("/home/daemon/sleep");
        $second = (int)$second;
        if($second) {        //让程序睡眠指定秒数
              sleep($second);
        }
    }
}
考虑3, 是否可以改成多线程的程序,让运行的效率更高?
这个只要把cron的10分钟起一个进程的限制改成每1分钟起一个进程就好了
这样能保证有10个线程在运行程序
但是有一个基本要求是:oPopMessageQueue()是一个原子操作(整个逻辑处理成功才算成功,有一个失败就需要回滚<事务>)

出处:http://www.cnblogs.com/yjf512/

本文版权归yjf512和cnBlog共有,欢迎转载,但未经作者同意必须保留此段声明

相关文章

  • PHP创建守护进程

    PHP 创建守护进程 执行守护进程

  • php守护进程

  • php 守护进程

    出处:http://www.cnblogs.com/yjf512/ 本文版权归yjf512和cnBlog共有,欢迎...

  • php实现守护进程

    何为守护进程 守护进程是在后台运行不受终端控制的进程(如输入、输出等)守护进程脱离终端的主要原因有两点: 用来启动...

  • PHP 实现守护进程

    1.简介 守护进程是一个在后台运行并且不受任何终端控制的进程。Unix操作系统有很多典型的守护进程(其数目根据需要...

  • 用Redis做一个消息队列

    PHP文件使用redis调用方法,操作入队列,守护进程文件中,使用redis方法操作出队列,然后执行业务逻辑 守护...

  • PHP进程守护和开机自启

    PHP守护进程的方式 借助nohup 和& 配合使用(验证OK) 在命令后面加上&符合,可以让启动的进程转到后台运...

  • 编写 PHP 守护进程程序

    守护进程(daemon),又称为常驻后台进程。该进程持续在后台运行,处理系统业务。它没有控制终端,不与前台交互。要...

  • php多进程--守护进程的实现

    守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事...

  • rsync服务企业应用

    守护进程服务企业应用: 守护进程多模块功能配置 守护进程的排除功能实践 守护进程来创建备份目录 守护进程的访问控制...

网友评论

    本文标题:php 守护进程

    本文链接:https://www.haomeiwen.com/subject/rluzixtx.html