一、swoole多进程实现简介
0、通过swoole实现多进程,主要借助swoole_process类
swoole_process::__construct(callable $function, bool $redirect_stdin_stdout = false, int $pipe_type = SOCK_DGRAM, bool $enable_coroutine = false);
1、简易实现demo[来自swoole官网]
$process = new swoole_process(function (swoole_process $worker) { $worker->write('Hello'); }, false); $process->start(); sleep(1); echo $process->read();
2、具体实现说明
2.0、通过swoole_process类创建子进程实例,回调函数$function中的逻辑在子进程中执行。
2.1、子进程中处理后的数据,可以通过write方法写入管道,父进程中可以通过子进程实例从管道中读取数据。即,进程间通信。
2.2、如果需要打印子进程中数据,参数$redirect_stdin_stdout需要设置为false。
3、通过函数getmypid()获取父子进程ID示例,以下内容保存在文件ipc.php中。
echo 'ppid = ' . getmypid(), PHP_EOL; $process = new swoole_process(function (swoole_process $worker) { $worker->write('Hello'); echo 'pid = ' . getmypid(), PHP_EOL; echo $worker->pid, PHP_EOL; sleep(5); }, false); $process->start(); echo $process->pid, PHP_EOL; sleep(1000); // 父进程中通过子进程的实例获取管道中的信息 echo $process->read();
4、执行结果
[root@242 process]# php ipc.php ppid = 1751 1752 pid = 1752 1752
# 开始能看到两个进程 [root@242 process]# ps -ef | grep ipc root 1751 1275 0 10:35 pts/0 00:00:00 php ipc.php root 1752 1751 0 10:35 pts/0 00:00:00 php ipc.php root 1754 1323 0 10:35 pts/1 00:00:00 grep --color=auto ipc # 查看进程关系 [root@242 process]# pstree -p 1751 php(1751)───php(1752) # 5秒之后子进程结束运行,变成僵尸进程 [root@242 process]# ps -ef | grep 1752 root 1752 1751 0 10:35 pts/0 00:00:00 <defunct> root 1759 1323 0 10:36 pts/1 00:00:00 grep --color=auto 1752
5、说明,创建的子进程结束后没有通过wait方法回收,我们看到已经变成了defunct进程。
wait()用法
while ($res = swoole_process::wait()) { echo PHP_EOL, 'Worker Exit, PID: ' . $res['pid'] . PHP_EOL; }
二、swoole多进程实践
算法:
0、每个进程通过用户ID获取一个用户信息,多个进程同时获取多个信息。
1、获取的全部用户信息,筛选用户名称返回。
/** * 多进程获取用户信息实例 * * @author salmonl <wcblks@gmail.com> * @since 2019-10-16 */ class Multi_Process { private $uids = []; private $workers = []; public function __construct($uids) { $this->uids = $uids; } /** * 启动多个进程执行任务 */ public function exec() { try { $count = count($this->uids); for ($i = 0; $i < $count; $i++) { $uid = $this->uids[$i]; $process = new swoole_process(function(swoole_process $worker) use ($uid) { // do task $res = $this->doTask($uid); $worker->write($res); }, true); $pid = $process->start(); $this->workers[$pid] = $process; } } catch (\Exception $e) { var_dump($e); } } /** * 模拟获取用户信息 * * @param int $uid 用户ID */ protected function doTask($uid) { $res = []; switch ($uid) { case 100: // get from api i.api.niliu.me/userinfo?uid=100 $res = ['id' => 100, 'name' => 'salmonl', 'age' => 30, 'sex' => 'male']; break; case 200: $res = ['id' => 200, 'name' => 'tom', 'age' => 38, 'sex' => 'male']; break; case 300: $res = ['id' => 300, 'name' => 'bob', 'age' => 24, 'sex' => 'female']; break; default: break; } // 休眠1秒 sleep(1); return json_encode($res); } /** * 输出 * * @param */ public function output() { foreach ($this->workers as $worker) { $user_info = json_decode($worker->read(), true); $names[] = $user_info['name']; } // 回收子进程 while ($res = swoole_process::wait()) { echo PHP_EOL, 'Worker Exit, PID: ' . $res['pid'] . PHP_EOL; } echo json_encode($names), PHP_EOL; } } $uids = [100, 200, 300]; $stime = microtime(true); $multi = new Multi_Process($uids); $multi->exec(); $multi->output(); $etime = microtime(true); echo 'exec time : ', round(($etime - $stime), 3), PHP_EOL;
输出结果
[root@242 process]# php multi_oop.php Worker Exit, PID: 1880 Worker Exit, PID: 1881 Worker Exit, PID: 1882 ["salmonl","tom","bob"] exec time : 1.01