swoole-Process多进程执行CURL任务

案例一:

备注:用时一秒同时执行多个CURL获取内容

<?php

use Swoole\Process;

echo 'Start Time:'.date("Y-m-d H:i:s",time());
$workers = [];

$urls = [
  'https://www.baidu.com',
  'https://www.sina.com.cn',
  'https://www.qq.com',
  'https://www.taobao.com'
];

for($i=0;$i<4;$i++){
  //子进程
    $process = new Process(function ($workers) use ($i,$urls) {
        //curl
        $content = curlData($urls[$i]);
        $workers->write($content.PHP_EOL);
    },true);
    $pid = $process->start();
    $workers[$pid] = $process;
}

//读取
foreach($workers as $process){
    echo $process->read();
}

/**
 * 模拟请求URL的内容 1s
 */
function curlData($url){
    //curl File_get_contents
    $url = file_get_contents($url);
    sleep(1);
    return $url.PHP_EOL;
}

echo 'Start End:'.date("Y-m-d H:i:s",time());

 

案例二:

<?php

use Swoole\Process;

//执行方案一
$is_value = 2;

if($is_value == 1){
    /**
     * 方案一:单进程发送10封邮件
     */
    $start_time = microtime(true);
    for ($k = 0;$k < 10;$k ++)
    {
        sleep(1);
        $res = sendEmail(rand(11111111,99999999)."@qq.com");
        echo $res.$k.PHP_EOL;
    }
    $end_time = microtime(TRUE);
    echo sprintf("use time:%.3f s\n", $end_time - $start_time);

}else{
    /**
     * 方案二:多进程发送10封邮件
     * swoole_process::__construct(callable $function, $redirect_stdin_stdout = false, $create_pipe = true);
     * $redirect_stdin_stdout,重定向子进程的标准输入和输出。启用此选项后,在子进程内输出内容将不是打印屏幕,
     * 而是写入到主进程管道(例如用echo打印的内容也写入管道).读取键盘输入将变为从管道中读取数据。默认为阻塞读取。
     * $create_pipe,是否创建管道,启用$redirect_stdin_stdout后,此选项将忽略用户参数,强制为true。
     * 如果子进程内没有进程间通信,可以设置为 false
     */
    $start_time = microtime(true);
    $workers = array();
    for ($i=0;$i<10;$i++){
        $process = new swoole_process(function($worker){
            $i = $worker->read();
            $res = sendEmail(rand(11111111,99999999)."@qq.com");
            $worker->write("第{$i}个邮件发送完毕!状态:".$res.PHP_EOL);
        },true);
        $pid = $process->start();
        $process->write($i);
        //echo $process->read().PHP_EOL; //同步阻塞读取管道数据,导致的后果就是父进程依次等待每个进程处理完并返回了内容,才走下一次循环
        $workers[] = $process;
        //解决方案1
        //使用swoole_event_add将管道加入到事件循环中,变为异步模式
        /*swoole_event_add($process->pipe, function($pipe) use($process) {
            echo $rec = $process->read();
            swoole_event_del($process->pipe);//socket处理完成后,从epoll事件中移除管道
        });*/
    }

    //主进程数据结果
    /**
     * 解决方案2
     * 原因是父进程读取子进程返回的数据的时候,是同步阻塞读取
     * 此方案就解决了同步阻塞读取数据的问题,统一获取子进程的返回数据
     *
     */
    foreach ($workers as $process){
        echo $process->read().PHP_EOL;
    }

    //子进程结束必须要执行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);
}

//邮件发送
function sendEmail($email){
    sleep(1);
    //发送邮件
    //返回发送的结果状态
    $str = 'send email:'.$email.'成功';
    return $str;
}

 

posted @ 2022-06-30 15:42  快乐的在一起  阅读(179)  评论(0编辑  收藏  举报