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

很少说,上代码php

<?php
$workers = [];
$worker_num = 2;

for($i = 0; $i < $worker_num; $i++)
{
    $process = new swoole_process('callback_function', false, false);
    $process->useQueue();
    $pid = $process->start();
    $workers[$pid] = $process;
    //echo "Master: new worker, PID=".$pid."\n";
}

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

    echo "From Master: $recv\n";

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

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

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

这段代码出自 消息队列html

我想说五个点swoole

  1. swoole_process 的建立默认是建立的管道,当想用消息队列时,记得把参数设成false(其实我发现不写也行)
  2. useQueue要在start的以前调用,
  3. pop方法 默认是阻塞的
  4. 必定必定要写wait(这里坑死很多人)

还有第五点注意事项,我接下来重点说,由于这个点卡了我很久。code

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

<?php
$workers = [];
$worker_num = 2;

for($i = 0; $i < $worker_num; $i++)
{
    $process = new swoole_process('callback_function',false,false);
    $process->useQueue();
    $pid = $process->start();
    $workers[$pid] = $process;
    //echo "Master: new worker, PID=".$pid."\n";
}

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

}

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

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

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

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

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

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

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

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

由于趁着第一个子进程睡觉的时候,主进程和第二个子进程把事情作了

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

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

这是我要说的第五点

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

好的,基本上遵照这五条,使用消息队列就不会有什么问题了。最后请记得升级本身的swoole版本,由于有些问题多是由于你的版本太老了

相关文章
相关标签/搜索