摘要:当子进程都完成了,主进程开始继续业务。是子进程的句柄子进程句柄向自己管道里写内容子进程句柄从自己的管道里面读取信息这里是子进程哦贴上运行结果喔,通讯是这样的。我们再看看创建进程时第二个参数的说明,重定向子进程的标准输入和输出。
进程管理模块
介绍看这里 swoole的process
大家可以先看看自己的swoole版本,在命令行里面敲
php --ri swoole
更多的php命令行使用,大家学习 php命令行参数
ok 我们直奔主题
怎么用
不多说,直接上代码
start(); echo PHP_EOL . $pid;// } function callback_function_we_write(swoole_process $worker){ echo PHP_EOL; var_dump($worker); echo PHP_EOL; }
运行结果如下
5445 object(swoole_process)#1 (3) { ["pipe"]=> int(3) ["callback"]=> string(26) "callback_function_we_write" ["pid"]=> int(5445) } 5446 object(swoole_process)#2 (3) { ["pipe"]=> int(5) ["callback"]=> string(26) "callback_function_we_write" ["pid"]=> int(5446) }
可以看到,我们使用 new swoole_process 创建进程,这里需要一个参数,也就是回调函数
当我们使用 $process->start()执行后,返回这个进程的pid ,也就是 $pid.
此时子进程启动,调用回调函数,并传一个参数 也就是 swoole_process 类型的 $worker
我故意输出了 $worker 看看里面有什么,结果有三个属性
pipe 进程的管道id 这个等说道进程间通信的时候再聊
pid 就是当前子进程的 pid 啦
callback 这个是我们自己写的回调函数名
到这里,我们就可以用多进程玩耍了,
比如,我们可以测试多进程的运行速度
start(); } function callback_function_we_write(swoole_process $worker){ for($i=0;$i<100000000;$i++){} echo PHP_EOL . time() ; }
我本机运行结果
1435563435 // 开始时间
1435563438 //进程1 结束时间
1435563440 //进程2 结束时间
1435563440 //进程3 结束时间
算三次 用了5s (其实一般是4s)
再玩一次
我本机运行结果
1435563704
1435563712这次用了8s
做了这些,我想说明一个问题
并不是说 单进程 要花8s 做完的活,我们用3个进程就能将时间缩小三倍了
嘛,因为这是我以前的误区
多进程还可以这样玩
start(); sleep(2); } while(1){ $ret = swoole_process::wait(); if ($ret){// $ret 是个数组 code是进程退出状态码, $pid = $ret["pid"]; echo PHP_EOL."Worker Exit, PID=" . $pid . PHP_EOL; }else{ break; } } function methodOne(swoole_process $worker){// 第一个处理 echo $worker->callback .PHP_EOL; } function methodTwo(swoole_process $worker){// 第二个处理 echo $worker->callback .PHP_EOL; } function methodThree(swoole_process $worker){// 第三个处理 echo $worker->callback .PHP_EOL; }我多加的sleep是为了运行时看得更清楚,你也可以去掉
这里我使用了 swoole_process::wait() 详解
目的是当子进程结束后,主进程能够知道。我们来想一个情景
过节了,妈妈要做饭,一看厨房里缺了 油,盐,糖,味精,十三香。于是吩咐儿子去小卖部买点回来。厨房这边也不能闲着,老妈要继续洗菜,切菜。等到调料买回来了,菜也洗好,切好了,开始炒,这边炒好了一个菜,就要立刻送到餐桌上。这个情景里面,显然使用了多进程,并且各进程做的不是同样的事情。当子进程都完成了,主进程开始继续业务。
现在有了一个问题,就拿上面的情景来说,儿子去买调味料,如果发现盐没有了,或者钱不够了怎么办,如何与妈妈联系呢? 这就是下面要说的 进程间的通信
进程间的通信Process 的通信方式有两种
管道
swoole_process->write(string $data);
swoole_process->read(int $buffer_size=8192);消息队列
swoole_process->useQueue();
swoole_process->push(string $data);
swoole_process->pop(int $maxsize = 8192);我们先说说管道
管道通讯这里我们要再次的提及进程的创建 new swoole_process
大家请看这里 进程的创建
第一个参数是回调函数,不说了
第二个参数含义等会我会结合例子来说
第三个参数是默认的 true,意思是创建管道,大家还记得回调函数里我特意将$worker输出看到的内容吗?object(swoole_process)#1 (3) { ["pipe"]=> int(3) ["callback"]=> string(26) "callback_function_we_write" ["pid"]=> int(5445) }关键是这里的 pipe 这个就是本进程的管道id
我们可以这样理解每次创建一个进程后,就会随之创建一个管道,主进程想和哪一个进程通信,就向那个进程的管道写入/读取数据。
ok,我们看看代码
start(); $workers[$pid] = $process;//将每一个进程的句柄存起来 } // 这里是主进程哦。 foreach($workers as $pid => $process){// $process 是子进程的句柄 $process->write("hello worker[$pid] ");//子进程句柄向自己管道里写内容 $process->write($data); echo "From Worker: ".$process->read();//子进程句柄从自己的管道里面读取信息 $process->read(); echo PHP_EOL.PHP_EOL; } function workerFunc(swoole_process $worker){//这里是子进程哦 $recv = $worker->read(); echo PHP_EOL. "From Master: $recv "; //send data to master $worker->write("hello master , this pipe is ". $worker->pipe ."; this pid is ".$worker->pid." "); sleep(2); $worker->exit(0); }贴上运行结果
From Master: hello worker[8205] From Worker: hello master , this pipe is 3; this pid is 8205 From Master: hello worker[8206] From Worker: hello master , this pipe is 5; this pid is 8206喔,通讯是这样的。
首先 将所有的子进程的句柄都存到 主进程的一个数组里,数组下标就是pid。
当主进程想和哪个进程通讯,就使用那个句柄向对应管道里面 写/读 数据,这样就实现了进程间的通讯。接着,我们稍微改一下,看看运行效果
$redirect_stdout = true;// 重定向输出 注意 这次我改成 true 了,其他没变 $worker_num = 2;//进程数量 $workers = [];//存放进程用的 for($i = 0; $i < $worker_num; $i++){ $process = new swoole_process("workerFunc",$redirect_stdout ); $pid = $process->start(); $workers[$pid] = $process;//将每一个进程的句柄存起来 } // 这里是主进程哦。 foreach($workers as $pid => $process){// $process 是子进程的句柄 $process->write("hello worker[$pid] ");//子进程句柄向自己管道里写内容 $process->write($data); echo "From Worker: ".$process->read();//子进程句柄从自己的管道里面读取信息 $process->read(); echo PHP_EOL.PHP_EOL; } function workerFunc(swoole_process $worker){//这里是子进程哦 $recv = $worker->read(); echo PHP_EOL. "From Master: $recv "; //send data to master $worker->write("hello master , this pipe is ". $worker->pipe ."; this pid is ".$worker->pid." "); sleep(2); $worker->exit(0); }输出结果
From Worker: From Master: hello worker[8007] From Worker: From Master: hello worker[8008]诶,不一样了有没有。我们再看看创建进程时第二个参数的说明
$redirect_stdin_stdout,重定向子进程的标准输入和输出。 启用此选项后,在进程内echo将不是打印屏幕,而是写入到管道。读取键盘输入将变为从管道中读取数据。 默认为阻塞读取。
我来说明一下,因为创建的时候指定了true,子进程中echo的内容就到了管道里面,而不是打印在屏幕上(这一点类似于php的ob缓存机制,大家想象一下)
消息队列
前面说了,进程的通讯是通过从管道里面读/写数据实现的,而 子进程 里 echo 的内容被 重定向到管道里面了,所以,主进程从管道里读到的内容,就是 子进程中 echo 的 内容。
也就造成了上面的 输出结果。我先来个链接 利用PHP操作Linux消息队列完成进程间通信
重点是这个文章里面的两个链接文章啊,大家等会看看
还有一个命令ipcs -q 查看当前的消息队列
这部分 下次讨论
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/20990.html
摘要:不多说,上代码这段代码出自消息队列我想说五个点的创建默认是创建的管道,当想用消息队列时,记得把参数设成其实我发现不写也行要在的之前调用,方法默认是阻塞的一定一定要写这里坑死不少人还有第五点注意事项,我接下来重点说,因为这个点卡了我好久。 不多说,上代码
摘要:原先用的多线程实现的支付结果回调服务,在后期运行中出现了服务停止的问题,在学习的过程中,发现可以用的进程管理模块实现多线程的功能,并且使用定时器功能实现进程监控在子进程退出的时候进行重启。 原先用PHP的Pthread多线程实现的支付结果回调服务,在后期运行中出现了服务停止的问题,在学习swoole的过程中,发现可以用swoole的Process进程管理模块实现多线程的功能,并且使用s...
摘要:消息队列更常见的用途是主进程分配任务,子进程消费执行。子进程前面加了个,这是为了防止父进程还未往消息队列中加入内容直接退出。 前面几节都是讲解pcntl扩展实现的多进程程序。本节给大家介绍swoole扩展的swoole_process模块。 swoole多进程 swoole_process 是swoole提供的进程管理模块,用来替代PHP的pcntl扩展。 首先,确保安装的swoole...
摘要:在中的应用官网源码解读号外号外欢迎大家我们开发组定了一个就线下聚一次的小目标上一篇源码解读反响还不错不少同学推荐再加一篇讲解一下中使用到的功能帮助大家开启的实战之旅服务器开发涉及到的相关技术领域的知识非常多不日积月累打好基础是很难真正 date: 2017-12-14 21:34:51title: swoole 在 swoft 中的应用 swoft 官网: https://www.sw...
摘要:配合模块,创建的子进程可以异步的事件驱动模式。默认为阻塞读取。函数用于将一个加入到的事件监听中。为事件类型的掩码,可选择关闭开启可读可写事件,如,,或者。在程序中使用,可以理解为在进程中将此注册到事件中。 Process Process是swoole内置的进程管理模块,用来替代PHP的pcntl扩展。 swoole_process支持重定向标准输入和输出,在子进程内echo不会打印屏...
阅读 2574·2021-10-19 11:41
阅读 2415·2021-09-01 10:32
阅读 3377·2019-08-29 15:21
阅读 1755·2019-08-29 12:20
阅读 1161·2019-08-29 12:13
阅读 599·2019-08-26 12:24
阅读 2520·2019-08-26 10:26
阅读 827·2019-08-23 18:40