Swoole的多进程模块介绍Swoole有自己的进程管理模块,用于替代PHP的pcntl扩展。需要注意的是,Process进程是系统中非常昂贵的资源,创建进程消耗很大。另外,创建过多的进程会导致进程切换开销显着增加。为什么不用pcntlpcntl不提供进程间通信的功能pcntl不支持标准输入输出的重定向pcntl只提供了fork等原始接口,使用简单容易出错只需调用write/read或push/流行音乐。swoole_process支持重定向标准输入输出。在子进程中,echo不会打印屏幕,而是写入管道。读取键盘输入可以重定向到管道读取数据swoole_process提供了exec接口,创建的进程可以执行其他程序,与原来的PHP父进程可以方便的通信创建进程函数原型:Swoole\Process::__construct(callable$function,$redirect_stdin_stdout=false,$create_pipe=true)$function,子进程创建成功后要执行的函数,底层会自动将该函数保存到对象的回调属性中。如果要改变执行的函数,可以给对象的回调属性$redirect_stdin_stdout赋一个新的函数来重定向子进程的标准输入输出。启用此选项后,子进程中的输出将不会打印到屏幕,而是写入主进程管道。读取键盘输入变成从管道读取数据。默认为阻塞读取。$create_pipe,是否创建管道,启用$redirect_stdin_stdout后,该选项将忽略用户参数,强制为true。如果子进程中没有进程间通信,则可以设置为false。swoole创建多个进程非常简单:newSwoole\Process('callback_function')就可以了。比如我要同时创建6个进程,只需要循环6次就可以了。假设前台要求后台执行三组任务,每组任务执行时间大约为一秒,我们采用多进程的形式来实现,这样可以缩短时间。for($i=0;$i<6;$i++){#创建了3个子进程$process=newSwoole\Process(function($process){sleep(1);echoPHP_EOL.posix_getpid().PHP_EOL;#获取子进程PID},false,true);$进程->开始();如果进程间的通信是一个非常简单的多进程执行任务,那么进程间就没有通信的必要了。实际中,很多业务都是对于那些需要通信的,比如发送邮件,如果自进程发送失败,那么必须通知主进程等等,swoole_process支持两种进程间的通信方式:pipe管道消息队列管道通信半双工:数据单向流动,一端只读,另一端只写。同步vs异步:默认是同步阻塞模式。您可以使用swoole_event_add()将管道添加到swoole的事件循环中。异步IO管道通信是swoole_process默认的通信方式。当然我们也可以在实例化的时候通过参数来设置:$process=newSwoole\Process('callback_function',false,true);如果我们打印$process,我们会发现,每创建一个进程,都会跟着创建一个管道,主进程要和哪个进程通信,就向那个进程的管道写入/读取数据。管道有两种方法,写入数据和读取数据。$process->write('data');#写数据$process->read()#读数据管道通信方式一:$worker=[];for($i=0;$i<3;$i++){$process=newSwoole\Process(function($process){var_dump('subprocess:'.$process->read());sleep(1);$process->write('subprocessdata');echoPHP_EOL.posix_getpid().PHP_EOL;},false,true);$pid=$process->start();$worker[$pid]=$process;//把对应的进程放到同一个数组中其中$process->write('主进程数据');//var_dump($process->read());//同步阻塞}foreach($workeras$w){var_dump('mainprocess:'.$w->read());}管道通信方式二:for($i=0;$i<3;$i++){$process=newSwoole\Process(function($process){var_dump('Subprocess:'.$process->read());sleep(1);$process->write('subprocessdata');echoPHP_EOL.posix_getpid().PHP_EOL;},false,true);$pid=$process->start();$process->write('主流程数据');//异步监听管道中的数据,读取事件监听,管道可读时触发swoole_event_add($process->pipe,function($pipe))use($process){var_dump('主进程:'.$process->read());});//var_dump($process->read());//同步阻塞}消息队列的通信消息队列:内核中存储的一系列消息列表都有一个msgKey,通过它可以不同的消息队列访问过。有数据大小限制,默认8192blockingvsnon-blocking:阻塞模式下pop()空消息队列/push()满消息队列会阻塞,非阻塞模式可以直接返回swoole中的消息队列:通信mode:默认为竞争模式,消息不能投递到指定的子进程。创建新的消息队列后,主进程可以使用消息队列,不能与管道一起使用。同样无法使用swoole事件循环步骤:启用消息队列作为进程间通信:boolswoole_process->useQueue(int$msgkey=0,int$mode=2);向消息队列发送数据:boolswoole_process->push(string$data);从队列字符串中提取数据swoole_process->pop(int$maxsize=8192);案例:for($i=0;$i<3;$i++){$process=newSwoole\Process(function($process){var_dump('subprocess:'.$process->pop());//$process->push('hellomainprocess');#pushtomainprocess});$process->useQueue(1,2|swoole_process::IPC_NOWAIT);//启用消息队列,竞争模式,非阻塞,可以被任何子进程接收$pid=$process->start();$process->push('你好子流程');#推送到子进程,不能作为管道使用//echo'Mainprocessmessage:'.$进程->弹出()。PHP_EOL;}感谢观看感谢您的耐心观看,希望对您有所帮助,也希望您能提出不同的意见,找到更有效的完成方式,共同学习,谢谢!
