基于swoole实现多进程处理耗时任务

版权声明:转载请注明来源 https://blog.csdn.net/u013702678/article/details/87890753

swoole提供了创建进程的简便方式,同时如果有进程池的需求,也是可以快速上手,因公司swoole较老,swoole原生提供的进程池不能使用,这里就用swoole_process实现了多进程处理耗时任务的需求。

这次的背景是这样的,有个每分钟1次的定时任务,这个定时任务启动后,会循环请求多个agent上的数据,最初的实现是通过for循环去请求各个agent的数据进行处理,这种模式有个固有缺陷,即单个agent的超时会操作后续其他agent的开始处理时间延长,而我们的业务必须是每次调度时,需要尽快把各个agent的数据处理完。

后续为了规避单个agent的超时影响,将原有的各个agent的处理拆分为多进程处理,规避了单个agent超时造成的影响。

下面的实现是每次fork进程,处理完业务后就退出了,这种模式不适合需要频繁启动进程的模式,因为太耗资源,请大家在学习时,注意抉择。

<?php
class ProcessRequestOneExistPool
{
    private $worker = [];
    private $work_num = 0;
    private $start_time = null;

    public function __construct($work_num)
    {
        $this->work_num = $work_num;
    }

    public function start($callable)
    {
        $this->start_time = microtime(true);

        for ($i=0;$i<$this->work_num;$i++)
        {
            $this->startWorker($i,$callable);
        }

        \swoole_process::signal(SIGCHLD, function ($sig) {
            while (true)
            {
                $ret = \swoole_process::wait(false);
                if($ret)
                {
                    if(isset($ret['pid']))
                    {
                        if(array_key_exists($ret['pid'],$this->worker))
                        {
                            unset($this->worker[$ret['pid']]);
                        }

                        if(empty($this->worker) || count($this->worker)==0)
                        {
                            echo "all poll work process end,now exit!!".PHP_EOL;
                            echo "cost time:".(microtime(true) - $this->start_time)." s".PHP_EOL;
                            exit;
                        }
                    } else {
                        break;
                    }
                } else {
                    break;
                }
            }
        });
    }

    private function startWorker($i,$callable)
    {
        $process = new \swoole_process(function (\swoole_process $process) use ($i,$callable) {
            call_user_func_array($callable,[$i]);
        }, false,0);
        $child_pid = $process->start();
        $this->worker[$child_pid] = $process;
    }
}

$s = new ProcessRequestOneExistPool(20);
echo "start time:".microtime(true).PHP_EOL;
$s->start(function () {
    sleep(1);
    echo "my is ".func_get_args()[0]." process,pid:".getmypid().PHP_EOL;
});

//output
start time:1550898368.2097
my is 0 process,pid:78598
my is 1 process,pid:78599
my is 2 process,pid:78600
my is 3 process,pid:78601
my is 14 process,pid:78612
my is 5 process,pid:78603
my is 6 process,pid:78604
my is 4 process,pid:78602
my is 7 process,pid:78605
my is 15 process,pid:78613
my is 8 process,pid:78606
my is 18 process,pid:78616
my is 17 process,pid:78615
my is 9 process,pid:78607
my is 16 process,pid:78614
my is 10 process,pid:78608
my is 13 process,pid:78611
my is 11 process,pid:78609
my is 12 process,pid:78610
my is 19 process,pid:78617
all poll work process end,now exit!!
cost time:1.052453994751 s

猜你喜欢

转载自blog.csdn.net/u013702678/article/details/87890753