PHP 進程間通訊——消息隊列(msg_queue)

PHP 進程間通訊——消息隊列php

本文不涉及PHP基礎庫安裝。詳細安裝說明,請參考官網,或期待後續博客分享。css

一、消息隊列函數準備shell

<?php
//生成一個消息隊列的key
$msg_key = ftok(__FILE__, 'a');
//產生一個消息隊列
$msg_queue = msg_get_queue($msg_key, 0666);
//檢測一個隊列是否存在 ,返回boolean值
$status = msg_queue_exists($msg_key);
//能夠查看當前隊列的一些詳細信息
$message_queue_status = msg_stat_queue($msg_queue);

//將一條消息加入消息隊列
msg_send($msg_queue, 1, "Hello, 1");
msg_send($msg_queue, 1, 'Hello, 2');
msg_send($msg_queue, 1, "Hello, 3");

//從消息隊列中讀取一條消息。
msg_receive($msg_queue, 1, $message_type, 1024, $message1);
msg_receive($msg_queue, 1, $message_type, 1024, $message2);
msg_receive($msg_queue, 1, $message_type, 1024, $message3);

//移除消息隊列
msg_remove_queue($msg_queue);
echo $message1.PHP_EOL;
echo $message2.PHP_EOL;
echo $message3.PHP_EOL;


/**
* msg_send 有三個必選參數
* resource $queue ,
* int $msgtype ,
* mixed $message
*
* 第一個必需要是隊列資源類型。resource(4) of type (sysvmsg queue)
* 第二個參數是消息類型,一個整形,且必須大於0.
* msg_send() sends a message of type msgtype (which MUST be greater than 0) to the message queue specified by queue.
* 第三個參數。是要發送的信息。能夠是字符串,也能夠是數組。默認會被serialize.
*/



/**
* msg_receive 的參數比較多。必需要填的參數有5個。
* resource $queue ,
* int $desiredmsgtype ,
* int &$msgtype ,
* int $maxsize ,
* mixed &$message
*
* 其中$desiredmsgtype .通過測試和官網描述不符,暫不解釋。
*
* $msgtype 。這個是msg_send 中所選定的msg_type.這是一個引用參數。
* The type of the message that was received will be stored in this parameter.
*
* $maxsize。
* The maximum size of message to be accepted is specified by the maxsize;
* if the message in the queue is larger than this size the function will fail (unless you set flags as described below).
* 這個參數聲明的是一個最大的消息大小,若是超過則會報錯。
*
* $message.
* 上文msg_send 發送的消息類型。
*/

二、多進程通訊實例數組

<?php
/**
* 這段代碼模擬了一個平常的任務。
* 第一個父進程產生了一個子進程。子進程又做爲父進程,產生10個子進程。
* 能夠簡化爲A -> B -> c,d,e... 等進程。
* 做爲A來講,只須要生產任務,而後交給B 來處理。B 則會將任務分配給10個子進程來進行處理。
*
*/


//設定腳本永不超時
set_time_limit(0);
$ftok = ftok(__FILE__, 'a');
$msg_queue = msg_get_queue($ftok);
$pidarr = [];

//產生子進程
$pid = pcntl_fork();
if ($pid) {
//父進程模擬生成一個特大的數組。
$arr = range(1,100000);

//將任務放進隊裏,讓多個子進程並行處理
foreach ($arr as $val) {
$status = msg_send($msg_queue,1, $val);
usleep(1000);
}
$pidarr[] = $pid;
msg_remove_queue($msg_queue);
} else {
//子進程收到任務後,fork10個子進程來處理任務。
for ($i =0; $i<10; $i++) {
$childpid = pcntl_fork();
if ($childpid) {
$pidarr[] = $childpid; //收集子進程processid
} else {
while (true) {
msg_receive($msg_queue, 0, $msg_type, 1024, $message);
if (!$message) exit(0);
echo $message.PHP_EOL;
usleep(1000);
}
}
}
}

//防止主進程先於子進程退出,造成殭屍進程
while (count($pidarr) > 0) {
foreach ($pidarr as $key => $pid) {
$status = pcntl_waitpid($pid, $status);
if ($status == -1 || $status > 0) {
unset($pidarr[$key]);
}
}
sleep(1);
}
?>

以上的示例只是爲了說明多進程通訊的應用示例,並未在真實的項目中應用。爲了示例方便,省略了不少的校驗條件。但做爲了解過程及原理來講,並不影響。
在執行while 循環時候,必需要使用usleep(1000) 以上。不然CPU可能會被撐爆。
以上的多進程通訊,沒有產生殭屍進程。得益於最後一段的while循環。
其原理在於,父進程在每次循環的時候都檢測子進程是否退出。若是退出,則父進程就會回收該子進程。而且將該進程從進程列表中刪除。
可使用ps aux |grep process.php來查看當前產生的進程數量。 其中process.php 是運行的文件名
效果以下:less

[root@roverliang~]# ps aux |grep php
74:root 4163 9.3 2.2 243908 22844 pts/1 S+ 17:42 0:00 php process.php
75:root 4164 0.0 0.3 229104 3924 pts/1 S+ 17:42 0:00 php process.php
76:root 4165 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
77:root 4166 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
78:root 4167 1.0 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
79:root 4168 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
80:root 4169 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
81:root 4170 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
82:root 4171 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
83:root 4172 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
84:root 4173 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
85:root 4174 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php

有疑問的話,能夠共同討論學習。博主也是剛學習這塊,若是有什麼不對的,但願能獲得指點,共同提升。函數

相關文章
相關標籤/搜索