php多进程的灵活运用,提高程序的效率问题。

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情

PHP很多时候都是单进程运行代码的,所以对于处理一些高并发的场景就不是很擅长。不过我们在cli命令模式下运行PHP程序很多时候是可以运用的多进程来提高运行效率的。定时发送邮件可以运用多进程,爬虫可以运用多进程等等,这样我们这些任务就能节约几倍的运行时间了。

函数介绍

pcntl_fock

在当前进程当前位置产生分支(子进程)。此函数创建了一个新的子进程后,子进程会继承父进程当前的上下文,和父进程一样从pcntl_fork()函数处继续向下执行,只是获取到的pcntl_fork()的返回值不同,我们便能从判断返回值来区分父进程和子进程,分配父进程和子进程去做不同的逻辑处理。

pcntl_fork()函数成功执行时会在父进程返回子进程的进程id(pid),因为系统的初始进程init进程的pid为1,后来产生进程的pid都会大于此进程,所以我们可以通过判断pcntl_fork()的返回值大于1来确实当前进程是父进程;

而在子进程中,此函数的返回值会是固定值0,我们也可以通过判断pcntl_fork()的返回值为0来确定子进程;

而pcntl_fork()函数在执行失败时,会在父进程返回-1,当然也不会有子进程产生。

posix_getpid

获取当前进场的pid。

pcntl_waitpid

等待或返回fork的子进程状态,如果指定的子进程在此函数调用时已经退出(俗称僵尸进程),此函数将立刻返回,并释放子进程的所有系统资源,此进程可以避免子进程变成僵尸进程,造成系统资源浪费;

posix_kill

它通过向子进程发送一个信号来操作子进程,在需要要时可以选择给子进程发送进程终止信号来终止子进程;

实现PHP版的多进程

在子进程运行的地方可以封装自己需要运行的代码,因为不同的进场是独立运行的所以要注意如果有顺序要求的业务要求就要慎重考虑了,例如一些没有顺序要求的,批量发送微信推送,邮件,批量导入没有顺序要求的数据到数据库等任务。

<?php

//子进程数组
$childs = array();

// Fork10个子进程
for ($i = 0; $i < 10; $i++) {
    $pid = pcntl_fork();
    if ($pid == -1) {
        die('Could not fork');
    }

    if ($pid) {
        echo "parent \n";
        $childs[] = $pid;
    } else {
        // 子进程代码运行
        // 子进程id
        $id = posix_getpid();
        sleep(2);
        echo "pid:$id sleep $i quit", PHP_EOL;
        // 子进程需要exit,防止子进程也进入for循环
        exit();
    }
}

while (count($childs) > 0) {
    foreach ($childs as $key => $pid) {
        $res = pcntl_waitpid($pid, $status, WNOHANG);
        //-1代表error, 大于0代表子进程已退出,返回的是子进程的pid,非阻塞时0代表没取到退出子进程
        if ($res == -1 || $res > 0) {
            unset($childs[$key]);
        }
    }
    sleep(1);
}
复制代码

现在基本已经实现了多进程了,如果还需要进一步优化就是可以通过使用pcntl的ticks来作为信号处理机制,可以利用这个机制来实现异步事件,可以利用pcntl_signal来注册信号和信号对于的回调函数,然后pcntl_signal_dispatch函数来检测是否有新的信号。我们就可以使用posix_kill这个函数来发送信号。这样就能实现父进程和子进程之间的一些联动业务操作了。

谢谢观看!!streetlamp敬上!

猜你喜欢

转载自juejin.im/post/7107030056018378765