Swoole进阶——01 进程(管道通信)


定义

进程就是正在运行的程序的一个实例。

例如,我们在某个终端去执行一个php脚本,这个时候就可以认为是开启了一个进程。



基本使用


1. 创建一个子进程对象

// 普通形式
$process = new swoole_process('callback_function', true);

// oop形式
swoole_process::__construct(callable $function, $redirect_stdin_stdout = false, $create_pipe = true);

// 启用命名空间
Swoole\Process::__construct(callable $function, $redirect_stdin_stdout = false, $create_pipe = true)

参数说明
  • $function,子进程创建成功后要执行的函数,底层会自动将函数保存到对象的callback属性上。如果希望更改执行的函数,可赋值新的函数到对象的callback属性。

  • $redirect_stdin_stdout,重定向子进程的标准输入和输出。启用此选项后,在子进程内输出内容将不是打印屏幕,而是写入到主进程管道。读取键盘输入将变为从管道中读取数据。默认为阻塞读取。

  • $pipe_type,管道类型,启用$redirect_stdin_stdout后,此选项将忽略用户参数,强制为1。如果子进程内没有进程间通信,可以设置为 0


管道类型

0:不创建管道

1:创建SOCK_STREAM类型管道

2:创建SOCK_DGRAM类型管道

启用$redirect_stdin_stdout 后,此选项将忽略用户参数,强制为1。

管道类型为DGRAM数据报时,read可以读取完整的一个数据包。

管道类型为STREAM时,read是流式的,需要自行处理包完整性问题。

对于数据完整性要求较高时,强烈建议不开启 $redirect_stdin_stdout。



2. 启动子进程

function swoole_process->start()

创建成功返回子进程的PID,创建失败返回false。

可使用swoole_errno和swoole_strerror得到错误码和错误信息。

  • $process->pid 属性为子进程的PID

  • $process->pipe 属性为管道的文件描述符

执行后子进程会保持父进程的内存和资源,如父进程内创建了一个redis连接,那么在子进程会保留此对象,所有操作都是对同一个连接进行的。



3. 往管道写入数据

function Process->write(string $data);
  • 在子进程内调用write,父进程可以调用read接收此数据

  • 在父进程内调用write,子进程可以调用read接收此数据



4. 从管道中读取数据

function Process->read(int $buffer_size=8192)

读取成功返回二进制数据字符串,读取失败返回false。



5. 执行外部程序

function Process->exec(string $execfile, array $args)
  • $execfile指定可执行文件的绝对路径,如 “/usr/bin/python”

  • $args是一个数组,是exec的参数列表,如 array(‘test.py’, 123),相当与python test.py 123


特别注意

$execfile必须使用绝对路径,否则会报文件不存在错误。

由于exec系统调用会使用指定的程序覆盖当前程序,子进程需要读写标准输出与父进程进行通信。

如果未指定redirect_stdin_stdout = true,执行exec后子进程与父进程无法通信。



简单例子

// 1.创建子进程对象
$process = new swoole_process(function(swoole_process $pro){
    
    // 3.调用外部程序
    $pro->exec("/usr/local/php/bin/php",[__DIR__.'../server/http.php']);

}, true);


// 2.启动子进程
$pid = $process->start();

echo "子进程id:".$pid.PHP_EOL;


// 4.回收子进程
swoole_process::wait();






使用场景


需求

有10个url地址,需要获取这10个地址里面的内容,写入文件或数据库。

PHP原始方案

同步执行这10个url,顺序获取一个个url里的内容。

问题:执行慢

Swoole process方案

引入swoole process,按需开启多个子进程执行。



例子

<?php

// 进程讲解例子

// 开始标志
echo "process-start-time".date("Ymd H:i:s").PHP_EOL;


// 1.定义子进程对象数组
$workers = [];


// 2.定义url数组
$urls = [
    'http:www.baidu.com',
    'http:www.qq.com',
    'http:www.sina.com',
    'http:www.jd.com',
    'http:www.imooc.com',
    'http:www.taobao.com',
];


// 3.PHP原生做法
// foreach($urls as $url){
//     $content[] = file_get_contents($url);
// }


// 3.swoole process做法
for($i = 0; $i < 6; $i++){

    // 4.创建子进程对象
    $process = new swoole_process(function(swoole_process $worker) use($i, $urls) {
        
        // 5.调用自定义方法
        $content = curlData($urls[$i]);
        //echo $content.PHP_EOL;

        // 6.往管道里写入内容
        $worker->write($content.PHP_EOL);

    },true);


    // 7.启动子进程
    $pid = $process->start();


    // 8.把子进程对象加到workers数组
    $workers[$pid] = $process;
}


// 9.打印workers
foreach ($workers as $process) {
    echo $process->read();
}


// 结束标志
echo "process-end-time".date("Ymd H:i:s");


// 自定义方法(模拟场景,非真实代码)
function curlData($url){
    sleep(1);
    return $url."success".PHP_EOL;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值