php進程間通信-消息隊列

爲什麼需要進程

進程是系統進行資源分配和調度的基本單位。進程作爲程序獨立運行的載體,保障程序正常執行。進程的存在使得操作系統資源的利用率大幅提升。

消息隊列

消息隊列是在消息的傳輸過程中保存消息的容器。消息隊列管理器相當於消息發送者和接收者的中介。消息隊列的主要目的是創建路由並且保證消息可靠傳遞;如果發送消息時接收者不可用,消息隊列會保留消息,直到有人接收它。

消息隊列可提供臨時存儲的功能並且能保證消息可靠的傳遞,我們正好使用它實現進程間通信。當然消息隊列不單單用於進程間通信,他的應用領域非常廣。比如消息隊列非常適用於解決消費者和生產者的問題,因爲生產者和消費者之間總會存在『速度差』。比如生產者突然少了10個,兩邊處理的速度就會不平衡,會導致排隊阻塞,服務不可用。這肯定不是我們想看到的,如果這時候引入消息隊列將兩個系統解耦,無論誰慢了都不會影響整體業務。

代碼實現

<?php
$childList = [];
$id = ftok(__FILE__,'m');//將路徑名和項目標識符轉換爲System V IPC密鑰
$msgQueue = msg_get_queue($id);//create a message queue
const MSG_TYPE = 1;
//生產者
function producer()
{
    global $msgQueue;
    $pid = posix_getpid();//獲取當前進程pid
    $i = rand(1,10);
    while ($i){
        $message = "生產者進程ID:{$pid},round:{$i}";
        msg_send($msgQueue,MSG_TYPE,$message);
        $i--;
    }
    echo "producer success\n";
}

//消費者
function consume()
{
    global $msgQueue;
    $pid = posix_getpid();
    while (msg_receive($msgQueue,MSG_TYPE,$msgType,1024,$message)){
        echo "消費者進程ID:{$pid},received message:{$message}\n";
    }
}

//創建進程
function createProgress($callBack){
    global $childList;
    //在當前進程當前位置產生分支(子進程)
    $pid = pcntl_fork();
    //父進程和子進程都會執行下面代碼
    if ($pid == -1){
        //錯誤處理:創建子進程失敗時返回-1.
        exit('fork error');
    }elseif ($pid == 0){
        //子進程得到的$pid爲0, 所以這裏是子進程執行的邏輯。
        $pid = posix_getpid();
        echo "child progress:{$pid}\n";
        $callBack();
        exit("{$pid}:child progress exit\n");
    }else{
        //父進程會得到子進程號,所以這裏是父進程執行的邏輯
        $childList[$pid] = 1;
    }
}

createProgress('producer');
createProgress('consume');

//等待子進程中斷,防止子進程成爲殭屍進程。
if (!empty($childList)){
    $pid = pcntl_wait($status);
    if ($pid > 0){
        unset($childList[$pid]);
        echo "{$pid}\n";
    }
}

運行結果

WX20191106-203720@2x.png

環境

  • pcntl擴展:主要的進程擴展,完成進程創建於等待操作。
  • sysvmsg擴展:實現system v方式的進程間通信之消息隊列。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章