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

一、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

参考:
https://wiki.swoole.com/wiki/page/p-process.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注