swoole_proces实现多进程
Posted 飞鸿影的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了swoole_proces实现多进程相关的知识,希望对你有一定的参考价值。
简介
swoole_process 是swoole提供的进程管理模块,用来替代php的pcntl扩展。
首先,确保安装的swoole版本大于1.7.2:
$ php --ri swoole
swoole
swoole support => enabled
Version => 1.10.1
实例说明
本例里待消费的是三个shell命令,会分别创建一个子进程来消费。消费的时候故意sleep了1秒,以便直观看到效果。
process_t1.php
<?php
$start_time = microtime(TRUE);
$cmds = [
"uname",
"date",
"whoami"
];
foreach ($cmds as $cmd) {
$process = new swoole_process( "my_process", true);
$process->start();
$process->write($cmd); //通过管道发数据到子进程
echo $rec = $process->read();//同步阻塞读取管道数据
}
//子进程
function my_process(swoole_process $worker){
sleep(1);//故意暂停1s
$cmd = $worker->read();
// $return = exec($cmd);//exec只会输出命令执行结果的最后一行内容,且需要显式打印输出
ob_start();
passthru($cmd);//执行外部程序并且显示未经处理的、原始输出,会直接打印输出。
$return = ob_get_clean();
if(!$return) $return = 'null';
$worker->write($return);//通过管道读取并返回数据,也可以使用echo代替write
// echo exec($return); //通过管道读取并返回数据
}
//子进程结束必须要执行wait进行回收,否则子进程会变成僵尸进程
while($ret = swoole_process::wait()){// $ret 是个数组 code是进程退出状态码,
$pid = $ret['pid'];
echo PHP_EOL."Worker Exit, PID=" . $pid . PHP_EOL;
}
$end_time = microtime(TRUE);
echo sprintf("use time:%.3f s\n", $end_time - $start_time);
命令行里运行:
$ php process_t1.php
Linux
Sat Apr 21 15:29:55 CST 2018
root
Worker Exit, PID=672
Worker Exit, PID=674
Worker Exit, PID=676
use time:3.080 s
大家会觉得很奇怪,为什么开了三个子进程,还是用了3秒,应该是1秒左右才对呀。
原因是父进程读取子进程返回的数据的时候,是同步阻塞读取:
echo $rec = $process->read();//同步阻塞读取管道数据
导致的后果就是父进程依次等待每个进程处理完并返回了内容,才走下一次循环。
解决方案1:
使用swoole_event_add
将管道加入到事件循环中,变为异步模式:
// echo $rec = $process->read();//同步阻塞读取管道数据
//使用swoole_event_add将管道加入到事件循环中,变为异步模式
swoole_event_add($process->pipe, function($pipe) use($process) {
echo $rec = $process->read();
swoole_event_del($process->pipe);//socket处理完成后,从epoll事件中移除管道
});
执行结果:
Worker Exit, PID=686
Worker Exit, PID=687
Worker Exit, PID=688
use time:1.060 s
Linux
Sat Apr 21 15:37:14 CST 2018
root
大家会发现,use time数据并不是最后打印出来的。已经是异步的了。 实际执行时间1s左右。
解决方案2:
先不获取子进程返回值,循环结束后统一返回:
foreach ($cmds as $cmd) {
$process = new swoole_process( "my_process", true);
$process->start();
$process->write($cmd); //通过管道发数据到子进程
$process_arr[] = $process;
}
foreach ($process_arr as $process){
echo $rec = $process->read();
}
执行结果:
Linux
Sat Apr 21 15:52:24 CST 2018
root
Worker Exit, PID=694
Worker Exit, PID=693
Worker Exit, PID=695
use time:1.061 s
参考
1、Process
https://wiki.swoole.com/wiki/page/p-process.html
2、swoole_process->read
https://wiki.swoole.com/wiki/page/217.html
以上是关于swoole_proces实现多进程的主要内容,如果未能解决你的问题,请参考以下文章