摘要:首先,確保安裝的版本大于實(shí)例說明本例里待消費(fèi)的是三個(gè)命令,會(huì)分別創(chuàng)建一個(gè)子進(jìn)程來消費(fèi)。通過管道發(fā)數(shù)據(jù)到子進(jìn)程。,重定向子進(jìn)程的標(biāo)準(zhǔn)輸入和輸出。
簡介
swoole_process 是swoole提供的進(jìn)程管理模塊,用來替代PHP的pcntl擴(kuò)展。
首先,確保安裝的swoole版本大于1.7.2:
$ php --ri swoole swoole swoole support => enabled Version => 1.10.1實(shí)例說明
本例里待消費(fèi)的是三個(gè)shell命令,會(huì)分別創(chuàng)建一個(gè)子進(jìn)程來消費(fèi)。消費(fèi)的時(shí)候故意sleep了1秒,以便直觀看到效果。
process_t1.php
start(); $process->write($cmd); //通過管道發(fā)數(shù)據(jù)到子進(jìn)程。管道是單向的:發(fā)出的數(shù)據(jù)必須由另一端讀取。不能讀取自己發(fā)出去的 echo $rec = $process->read();//同步阻塞讀取管道數(shù)據(jù) } //子進(jìn)程創(chuàng)建成功后要執(zhí)行的函數(shù) function my_process(swoole_process $worker){ sleep(1);//暫停1s $cmd = $worker->read(); // $return = exec($cmd);//exec只會(huì)輸出命令執(zhí)行結(jié)果的最后一行內(nèi)容,且需要顯式打印輸出 ob_start(); passthru($cmd);//執(zhí)行外部程序并且顯示未經(jīng)處理的、原始輸出,會(huì)直接打印輸出。 $return = ob_get_clean(); if(!$return) $return = "null"; $worker->write($return);//寫入數(shù)據(jù)到管道 } //子進(jìn)程結(jié)束必須要執(zhí)行wait進(jìn)行回收,否則子進(jìn)程會(huì)變成僵尸進(jìn)程 while($ret = swoole_process::wait()){// $ret 是個(gè)數(shù)組 code是進(jìn)程退出狀態(tài)碼, $pid = $ret["pid"]; echo PHP_EOL."Worker Exit, PID=" . $pid . PHP_EOL; } $end_time = microtime(TRUE); echo sprintf("use time:%.3f s ", $end_time - $start_time);
命令行里運(yùn)行:
$ php process_t1.php Linux Sat Apr 21 15:29:55 CST 2018 root Worker Exit, PID=672 Worker Exit, PID=674 Worker Exit, PID=676 use time:3.080 s
大家會(huì)覺得很奇怪,為什么開了三個(gè)子進(jìn)程,還是用了3秒,應(yīng)該是1秒左右才對呀。
原因是父進(jìn)程讀取子進(jìn)程返回的數(shù)據(jù)的時(shí)候,是同步阻塞讀取:
echo $rec = $process->read();//同步阻塞讀取管道數(shù)據(jù)
導(dǎo)致的后果就是父進(jìn)程依次等待每個(gè)進(jìn)程處理完并返回了內(nèi)容,才走下一次循環(huán)。
解決方案1:
使用swoole_event_add將管道加入到事件循環(huán)中,變?yōu)楫惒侥J剑?/p>
// echo $rec = $process->read();//同步阻塞讀取管道數(shù)據(jù) //使用swoole_event_add將管道加入到事件循環(huán)中,變?yōu)楫惒侥J?swoole_event_add($process->pipe, function($pipe) use($process) { echo $rec = $process->read(); swoole_event_del($process->pipe);//socket處理完成后,從epoll事件中移除管道 });
執(zhí)行結(jié)果:
Worker Exit, PID=686 Worker Exit, PID=687 Worker Exit, PID=688 use time:1.060 s Linux Sat Apr 21 15:37:14 CST 2018 root
大家會(huì)發(fā)現(xiàn),use time數(shù)據(jù)并不是最后打印出來的。已經(jīng)是異步的了。 實(shí)際執(zhí)行時(shí)間1s左右。
解決方案2:
先不獲取子進(jìn)程返回值,循環(huán)結(jié)束后統(tǒng)一返回:
foreach ($cmds as $cmd) { $process = new swoole_process( "my_process", true); $process->start(); $process->write($cmd); //通過管道發(fā)數(shù)據(jù)到子進(jìn)程 $process_arr[] = $process; } foreach ($process_arr as $process){ echo $rec = $process->read(); }
執(zhí)行結(jié)果:
Linux Sat Apr 21 15:52:24 CST 2018 root Worker Exit, PID=694 Worker Exit, PID=693 Worker Exit, PID=695 use time:1.061 s函數(shù)原型
swoole_process::__construct(callable $function, $redirect_stdin_stdout = false, $create_pipe = true);
第一個(gè)參數(shù)是子進(jìn)程創(chuàng)建成功后要執(zhí)行的函數(shù)。
$redirect_stdin_stdout,重定向子進(jìn)程的標(biāo)準(zhǔn)輸入和輸出。啟用此選項(xiàng)后,在子進(jìn)程內(nèi)輸出內(nèi)容將不是打印屏幕,而是寫入到主進(jìn)程管道(例如用echo打印的內(nèi)容也寫入管道)。讀取鍵盤輸入將變?yōu)閺墓艿乐凶x取數(shù)據(jù)。默認(rèn)為阻塞讀取。
$create_pipe,是否創(chuàng)建管道,啟用$redirect_stdin_stdout后,此選項(xiàng)將忽略用戶參數(shù),強(qiáng)制為true。如果子進(jìn)程內(nèi)沒有進(jìn)程間通信,可以設(shè)置為 false
注意:swoole_process在最新的1.8.0版本已經(jīng)禁止在Web環(huán)境中使用了,所以也只能支持命令行。這時(shí)候如果要做并發(fā),multi-curl是不錯(cuò)的選擇。
進(jìn)程常駐后臺(tái)如果跑的服務(wù)需要一直常駐后臺(tái),可以在$process->start();前面加上:
swoole_process::daemon();
服務(wù)會(huì)在后臺(tái)運(yùn)行。
更多示例 多進(jìn)程獲取網(wǎng)頁狀態(tài)碼$url) { $process = new swoole_process(function(swoole_process $worker) use ($url){ $code = getHttpCode($url); $worker->write($code); }, true); $process->start(); swoole_event_add($process->pipe, function($pipe) use($process, $url) { echo sprintf("%s code: %s ", $url, $process->read()); swoole_event_del($pipe); }); } echo "ok. "; while($ret = swoole_process::wait()){ // echo PHP_EOL."Worker Exit, PID=" . $ret["pid"] . PHP_EOL; } /** * 獲取網(wǎng)頁http code */ function getHttpCode($url){ $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 0); // curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "HEAD"); curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //不驗(yàn)證證書 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //不驗(yàn)證證書 curl_setopt ($ch, CURLOPT_TIMEOUT_MS, 1000);//超時(shí)時(shí)間 curl_exec($ch); $info = curl_getinfo($ch); curl_close($ch); return (string)$info["http_code"]; }
運(yùn)行:
$ php process_get.php ok. http://www.52fhy.com code: 403 http://www.52fhy.com/1 code: 404 https://www.baidu.com code: 200 https://www.52fhy.com code: 403使用消息隊(duì)列通信
push($url.": ".$code); } $worker->push("exit"); }, false, false); //不創(chuàng)建管道 $process->useQueue(1, 2); //使用消息隊(duì)列。消息隊(duì)列通信方式與管道不可共用。消息隊(duì)列不支持EventLoop,使用消息隊(duì)列后只能使用同步阻塞模式非阻塞 $process->start(); while(1){ $ret = $process->pop(); if($ret == "exit") break; echo sprintf("%s ", $ret); } echo "ok. "; while($ret = swoole_process::wait()){ echo PHP_EOL."Worker Exit, PID=" . $ret["pid"] . PHP_EOL; } /** * 獲取網(wǎng)頁http code */ function getHttpCode($url){ //省略 }
運(yùn)行:
$ php process_get_queue.php https://www.baidu.com: 200 http://www.52fhy.com: 403 http://www.52fhy.com/1: 404 https://www.52fhy.com: 403 ok. Worker Exit, PID=1222參考
1、Process
https://wiki.swoole.com/wiki/...
2、swoole_process->read
https://wiki.swoole.com/wiki/...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/28640.html
摘要:消息隊(duì)列更常見的用途是主進(jìn)程分配任務(wù),子進(jìn)程消費(fèi)執(zhí)行。子進(jìn)程前面加了個(gè),這是為了防止父進(jìn)程還未往消息隊(duì)列中加入內(nèi)容直接退出。 前面幾節(jié)都是講解pcntl擴(kuò)展實(shí)現(xiàn)的多進(jìn)程程序。本節(jié)給大家介紹swoole擴(kuò)展的swoole_process模塊。 swoole多進(jìn)程 swoole_process 是swoole提供的進(jìn)程管理模塊,用來替代PHP的pcntl擴(kuò)展。 首先,確保安裝的swoole...
摘要:本文使用與完成一個(gè)的進(jìn)程池,并且支持動(dòng)態(tài)創(chuàng)建新進(jìn)程。接著遍歷所有的進(jìn)程,并且加入中,設(shè)置可讀事件,用于接收子進(jìn)程的空閑信號(hào)。最后每隔一秒向進(jìn)程投遞任務(wù)。由于只模擬了十次任務(wù),則第十個(gè)任務(wù)完成之后在父進(jìn)程中發(fā)送使所有子進(jìn)程退出。 swoole_process 主要是用來代替 PHP 的 pcntl 擴(kuò)展。我們知道 pcntl 是用來進(jìn)行多進(jìn)程編程的,而 pcntl 只提供了 fork 這...
摘要:清空主進(jìn)程殘留的定時(shí)器與信號(hào)。設(shè)定為執(zhí)行回調(diào)函數(shù)如果在回調(diào)函數(shù)中調(diào)用了異步系統(tǒng),啟動(dòng)函數(shù)進(jìn)行事件循環(huán)。因此為了區(qū)分兩者,規(guī)定并不允許兩者同時(shí)存在。 前言 swoole-1.7.2 增加了一個(gè)進(jìn)程管理模塊,用來替代 PHP 的 pcntl 擴(kuò)展。 PHP自帶的pcntl,存在很多不足,如 pcntl 沒有提供進(jìn)程間通信的功能 pcntl 不支持重定向標(biāo)準(zhǔn)輸入和輸出 pcntl 只...
摘要:從入門到放棄三一進(jìn)程子進(jìn)程創(chuàng)建成功后要執(zhí)行的函數(shù)重定向子進(jìn)程的標(biāo)準(zhǔn)輸入和輸出。默認(rèn)為阻塞讀取。是否創(chuàng)建管道,啟用后,此選項(xiàng)將忽略用戶參數(shù),強(qiáng)制為。 swoole——從入門到放棄(三) 一、進(jìn)程 swoole_process SwooleProcess swoole_process::__construct(callable $function, $redirect_stdin...
閱讀 1839·2021-11-11 16:55
閱讀 761·2019-08-30 15:53
閱讀 3600·2019-08-30 15:45
閱讀 748·2019-08-30 14:10
閱讀 3277·2019-08-30 12:46
閱讀 2134·2019-08-29 13:15
閱讀 2035·2019-08-26 13:48
閱讀 943·2019-08-26 12:23