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版本,由於有些問題多是由於你的版本太老了

相關文章
相關標籤/搜索