资讯专栏INFORMATION COLUMN

swoole教程第一节:进程管理模块(Process)-中(消息队列)

A Loity / 486人阅读

摘要:不多说,上代码这段代码出自消息队列我想说五个点的创建默认是创建的管道,当想用消息队列时,记得把参数设成其实我发现不写也行要在的之前调用,方法默认是阻塞的一定一定要写这里坑死不少人还有第五点注意事项,我接下来重点说,因为这个点卡了我好久。

不多说,上代码

useQueue();
    $pid = $process->start();
    $workers[$pid] = $process;
    //echo "Master: new worker, PID=".$pid."
";
}

function callback_function(swoole_process $worker)
{
    //echo "Worker: start. PID=".$worker->pid."
";
    //recv data from master
    $recv = $worker->pop();

    echo "From Master: $recv
";

    sleep(2);
    $worker->exit(0);
}

foreach($workers as $pid => $process)
{
    $process->push("hello worker[$pid]
");
}

for($i = 0; $i < $worker_num; $i++)
{
    $ret = swoole_process::wait();
    $pid = $ret["pid"];
    unset($workers[$pid]);
    echo "Worker Exit, PID=".$pid.PHP_EOL;
}

这段代码出自 消息队列

我想说五个点

swoole_process 的创建默认是创建的管道,当想用消息队列时,记得把参数设成false(其实我发现不写也行)

useQueue要在start的之前调用,

pop方法 默认是阻塞的

一定一定要写wait(这里坑死不少人)

还有第五点注意事项,我接下来重点说,因为这个点卡了我好久。

嘛,demo里面只是说主进程向子进程发数据,没有子进程向主进程发数据,我就来加上吧

useQueue();
    $pid = $process->start();
    $workers[$pid] = $process;
    //echo "Master: new worker, PID=".$pid."
";
}

function callback_function(swoole_process $worker)
{
    //echo "Worker: start. PID=".$worker->pid."
";
    //recv data from master
    $recv = $worker->pop();
    echo "From Master: $recv
";
    $worker->push(" 
   hehe   
 ");//这里子进程向主进程发送  hehe
    sleep(2);//注意这里有个sleep
    $worker->exit(0);

}

foreach($workers as $pid => $process)
{
    $process->push("hello worker[$pid]
");
    $result = $process->pop();
    echo "From worker: $result
";//这里主进程,接受到的子进程的数据
}

for($i = 0; $i < $worker_num; $i++)
{
    $ret = swoole_process::wait();
    $pid = $ret["pid"];
    unset($workers[$pid]);
    echo "Worker Exit, PID=".$pid.PHP_EOL;
}

运行结果完美,我就不贴了,
我看着代码,忽然发现自己没把sleep删掉,然后噩梦开始
大家把上面代码的sleep注释后运行看看,我这里贴上我的运行结果

From Master: hello worker[3667]

From worker:  
   hehe   

PHP Warning:  swoole_process::push(): msgsnd() failed. Error: Invalid argument[22] in /home/sun/learn/swoole/process/demo.php on line 28
PHP Warning:  swoole_process::pop(): msgrcv() failed. Error: Invalid argument[22] in /home/sun/learn/swoole/process/demo.php on line 29
From worker: 
PHP Warning:  swoole_process::pop(): msgrcv() failed. Error: Identifier removed[43] in /home/sun/learn/swoole/process/demo.php on line 18
From Master: 
PHP Warning:  swoole_process::push(): msgsnd() failed. Error: Invalid argument[22] in /home/sun/learn/swoole/process/demo.php on line 20
Worker Exit, PID=3668
Worker Exit, PID=3667

这就是我的报错,我看这个错误,发现第一个进程是完美执行的,和预先想的一样,错误出在主进程第二次发送消息到消息队列时出现的,主进程的数据发送出错了

哎呀,怎么回事,不明白。
其实故事是这样的
主进程创建两个子进程,这里没问题
主进程向第一个子进程发数据,第一个子进程收到后向主进程回发数据,这里也没问题
主进程再向第二个子进程发数据,好,出问题了,
那么 问题来了,第一个子进程做了什么我们不知道的事情?
请看这里 子进程临死前做了什么

  

$status是退出进程的状态码,如果为0表示正常结束,会继续执行PHP的shutdown_function,其他扩展的 清理工作

第一个子进程临死前把消息队列给埋了

换句话说,主进程再想往消息队列里写东西时写不了了,因为没有消息队列了。

那为什么刚开始有sleep的时候就没事呢?

因为趁着第一个子进程睡觉的时候,主进程和第二个子进程把事情做了

那么我们怎么办?怎么才能不让子进程摧毁消息队列??

  

把 swoole_process->exit(0) 改成 swoole_process->exit(1)了

这是我要说的第五点

  

多个子进程使用消息队列通讯一定写上 $process->exit(1)

好的,基本上遵守这五条,使用消息队列就不会有什么问题了。最后请记得升级自己的swoole版本,因为有些问题可能是因为你的版本太老了

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/21065.html

相关文章

  • swoole教程一节:进程管理模块(Process)-上

    摘要:当子进程都完成了,主进程开始继续业务。是子进程的句柄子进程句柄向自己管道里写内容子进程句柄从自己的管道里面读取信息这里是子进程哦贴上运行结果喔,通讯是这样的。我们再看看创建进程时第二个参数的说明,重定向子进程的标准输入和输出。 进程管理模块 介绍看这里 swoole的process 大家可以先看看自己的swoole版本,在命令行里面敲 php --ri swoole ...

    Towers 评论0 收藏0
  • PHP多进程系列笔记(五)

    摘要:消息队列更常见的用途是主进程分配任务,子进程消费执行。子进程前面加了个,这是为了防止父进程还未往消息队列中加入内容直接退出。 前面几节都是讲解pcntl扩展实现的多进程程序。本节给大家介绍swoole扩展的swoole_process模块。 swoole多进程 swoole_process 是swoole提供的进程管理模块,用来替代PHP的pcntl扩展。 首先,确保安装的swoole...

    qianfeng 评论0 收藏0
  • Swoole-2.1.2 进程模块的使用

    摘要:在版本中我们将的进程管理模块封装成了类,现在可以在代码中使用的进程管理器了。提供的进程管理器来自于,经过大量生产项目验证,稳定性和健壮性都非常高。三任务投递进程管理器自带了消息队列和消息投递的支持。 在Swoole-2.1.2版本中我们将Server的进程管理模块封装成了PHP类,现在可以在PHP代码中使用Swoole的进程管理器了。 在实际项目中经常需要写一些长期运行的脚本,如基于r...

    ZoomQuiet 评论0 收藏0
  • Swoft 源码剖析 - Swoole和Swoft的那些事(Task投递/定时任务篇)

    摘要:作为定时任务的执行者,通过每唤醒自身一次,然后把执行表遍历一次,挑选当下需要执行的任务,通过投递出去并更新该任务执行表中的状态。 作者:bromine链接:https://www.jianshu.com/p/b44...來源:简书著作权归作者所有,本文已获得作者授权转载,并对原文进行了重新的排版。Swoft Github: https://github.com/swoft-clou.....

    vvpvvp 评论0 收藏0
  • swoole_process父子进程管道通信案例

    摘要:话不多说直接上代码创建的子进程获取异步获取更高性能启动子进程子进程处理逻辑异步非阻塞网关连接失败读取父进程管道消息父进程获取子进程的管道消息子进程消息子进程的客户端可以忽略不计,本只是 话不多说直接上代码 创建的子进程: public function __construct() { $this->redis = Container::get(SwooleR...

    Cheng_Gang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<