简介swoole_process是swoole提供的一个进程管理模块,用于替代PHP的pcntl扩展。首先确保安装的swoole版本大于1.7.2:$php--riswooleswooleswoolesupport=>enabledVersion=>1.10.1示例说明本示例中要使用三个shell命令,一个子进程将为消费而创造。消费的时候特意休眠1秒,这样可以直观的看到效果。process_t1.php开始();$process->write($cmd);//通过管道向子进程发送数据。管道是单向的:发出的数据必须由另一端读取。读不到echo$rec=$process->read();//同步阻塞读管道数据}//子进程创建成功后要执行的函数functionmy_process(swoole_process$worker){sleep(1);//暂停1s$cmd=$worker->read();//$return=exec($cmd);//exec只会输出命令执行结果的最后一行,需要显式打印出来ob_start();passthru($cmd);//执行外部程序并显示未处理的原始输出,并直接打印输出。$return=ob_get_clean();如果(!$return)$return='null';$worker->write($return);//向管道写入数据}//子进程结束必须执行等待回收,否则子进程会变成僵尸进程while($ret=swoole_process::wait()){//$ret是一个数组code是进程退出状态码,$pid=$ret['pid'];echoPHP_EOL."WorkerExit,PID=".$pid。PHP_EOL;}$end_time=microtime(TRUE);echosprintf("使用时间:%.3fs\n",$end_time-$start_time);在命令行运行:$phpprocess_t1.phpLinuxSatApr2115:29:55CST2018rootWorkerExit,PID=672WorkerExit,PID=674WorkerExit,PID=676usetime:3.080s大家会觉得很奇怪,为什么花了3秒打开三个子进程,应该是1秒左右。原因是父进程在读取子进程返回的数据时是同步读取的:echo$rec=$process->read();//同步阻塞管道数据读取的后果是父进程等待每个进程处理完并返回内容后,进入下一个循环。方案一:使用swoole_event_add将管道加入事件循环,改为异步模式://echo$rec=$process->read();//同步阻塞读取管道数据//使用swoole_event_add将管道加入事件循环event循环中,变成异步模式swoole_event_add($process->pipe,function($pipe)use($process){echo$rec=$process->read();swoole_event_del($process->pipe);//socket处理完成后,从epoll事件中移除管道});执行结果:WorkerExit,PID=686WorkerExit,PID=687WorkerExit,PID=688usetime:1.060sLinuxSatApr2115:37:14CST2018root你会发现,使用时间数据并没有最后打印出来。已经是异步的。实际执行时间约为1s。方案二:先不获取子进程的返回值,循环结束后统一返回:foreach($cmdsas$cmd){$process=newswoole_process("my_process",true);$进程->开始();$进程->写入($cmd);//通过管道向子进程发送数据$process_arr[]=$process;}foreach($process_arras$process){echo$rec=$process->read();}执行结果:LinuxSatApr2115:52:24CST2018rootWorkerExit,PID=694WorkerExit,PID=693WorkerExit,PID=695usetime:1.061sfunctionprototypeswoole_process::__construct(callable$function,$redirect_stdin_stdout=false,$create_pipe=true);第一个参数是子进程创建成功后要执行的函数。$redirect_stdin_stdout,重定向子进程的标准输入输出。启用该选项后,子进程中的输出内容不会打印到屏幕上,而是写入到主进程管道中(例如echo打印的内容也会写入到管道中)。读取键盘输入变成从管道读取数据。默认为阻塞读取。$create_pipe,是否创建管道,启用$redirect_stdin_stdout后,该选项将忽略用户参数,强制为true。如果子进程中没有进程间通信,可以设置为false。注意:swoole_process在最新的1.8.0版本已经禁止在Web环境下使用,所以只能支持命令行。这时候如果要做并发,multi-curl是一个不错的选择。该进程驻留在后台。如果运行的服务需要一直驻留在后台,可以添加:swoole_process::daemon();在$process->start();前面该服务将在后台运行。更多例子多进程获取网页状态码//www.52fhy.com/1','https://www.52fhy.com',];foreach($urlsas$key=>$url){$process=newswoole_process(function(swoole_process$worker)use($url){$code=getHttpCode($url);$worker->write($code);}},真的);$进程->开始();swoole_event_add($process->pipe,function($pipe)use($process,$url){echosprintf("%scode:%s\n",$url,$process->read());swoole_event_del($pipe);});}echo"ok.\n";while($ret=swoole_process::wait()){//echoPHP_EOL."WorkerExit,PID=".$ret['pid']。PHP_EOL;}/***获取网页http代码*/functiongetHttpCode($url){$ch=curl_init();curl_setopt($ch,CURLOPT_URL,$url);curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);curl_setopt($ch,CURLOPT_HEADER,0);//curl_setopt($ch,CURLOPT_CUSTOMREQUEST,"HEAD");curl_setopt($ch,CURLOPT_NOB奥迪,真的);curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);//不验证证书curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);//不验证证书curl_setopt($ch,CURLOPT_TIMEOUT_MS,1000);//超时curl_exec($ch);$info=curl_getinfo($ch);curl_close($ch);return(string)$info['http_code'];}运行:$phpprocess_get.phpok.http://www.52fhy.com代码:??403http://www.52fhy.com/1代码:404https://www.baidu.com代码:200https://www.52fhy.com代码:403使用消息队列通信push($url.':'.$code);}$worker->push('exit');},假的,假的);//不创建管道$process->useQueue(1,2);//使用消息队列消息队列的通信方式不能与管道共享。消息队列不支持EventLoop。使用消息队列后,只能使用非阻塞的同步阻塞方式$process->start();while(1){$ret=$process->pop();如果($ret=='退出')中断;echosprintf("%s\n",$ret);}echo"ok.\n";while($ret=swoole_process::wait()){echoPHP_EOL."WorkerExit,PID=".$ret['pid'].PHP_EOL;}/***获取网页http代码*/functiongetHttpCode($url){//省略}run:$phpprocess_get_queue.phphttps://www.baidu.com:200http://www.52fhy.com:403http://www.52fhy.com/1:404https://www.52fhy.com:403ok.Worker退出,PID=1222参考1,流程https://wiki.swoole.com/wiki/...2.swoole_process->阅读https://wiki.swoole.com/wiki/...
