先了解一下process和event loopphp
除了異步Server
和Client
庫以外,Swoole
擴展還提供了直接操做底層epoll/kqueue
事件循環的接口。可將其餘擴展建立的socket
,PHP
代碼中stream/socket
擴展建立的socket
等加入到Swoole
的EventLoop
中。react
Process::signal
設置的信號處理回調函數Event::defer
設置的延遲執行函數Timer::tick
和Timer::after
設置的定時器回調函數Event::cycle
設置的週期回調函數swoole_event_add
函數用於將一個socket加入到底層的reactor
事件監聽中。此函數能夠用在Server
或Client
模式下linux
參數1能夠爲如下四種類型:redis
int
,就是文件描述符,包括swoole_client->$sock
、swoole_process->$pipe
或者其餘fd
stream
資源,就是stream_socket_client/fsockopen
建立的資源sockets
資源,就是sockets
擴展中socket_create
建立的資源,須要在編譯時加入 ./configure --enable-sockets
object
,swoole_process
或swoole_client
,底層自動轉換爲管道或客戶端鏈接的socket
參數2
爲可讀回調函數,參數3
爲可寫事件回調,能夠是字符串函數名、對象+方法、類靜態方法或匿名函數,當此socket
可讀時回調指定的函數。shell
參數4
爲事件類型的掩碼,可選擇關閉/開啓可讀可寫事件,如SWOOLE_EVENT_READ
,SWOOLE_EVENT_WRITE
,或者SWOOLE_EVENT_READ | SWOOLE_EVENT_WRITE
編程
在 Server 程序中使用時,必須在 Worker 進程啓動後使用。在 Server::start 以前不得調用任何異步 IO 接口
在fpm當中一個請求結束了線程就被關掉了,註冊的事件就不會再去監聽了服務器
event lop實例:swoole
命令符聊天室php7
主要應用點:curl
異步讀取來自副武器的數據
異步讀取來自終端的輸入
手動退出聊天室
監聽服務器的讀和寫操做
服務端是不會挺中止的
process
curl實例:多進程執行任務和執行一個外部的程序
<?php /** * Created by PhpStorm. * User: baidu * Date: 18/3/17 * Time: 上午12:31 */ echo "process-start-time:".date("Ymd H:i:s"); $workers = []; $urls = [ 'http://baidu.com', 'http://sina.com.cn', 'http://qq.com', 'http://baidu.com?search=singwa', 'http://baidu.com?search=singwa2', 'http://baidu.com?search=imooc', ]; for($i = 0; $i < 6; $i++) { // 子進程 $process = new swoole_process(function(swoole_process $worker) use($i, $urls) { // curl $content = curlData($urls[$i]); //echo $content.PHP_EOL; $worker->write($content.PHP_EOL); }, true); $pid = $process->start(); $workers[$pid] = $process; } foreach($workers as $process) { echo $process->read(); } /** * 模擬請求URL的內容 1s * @param $url * @return string */ function curlData($url) { // curl file_get_contents sleep(1); return $url . "success".PHP_EOL; } echo "process-end-time:".date("Ymd H:i:s");
$process = new swoole_process(function(swoole_process $pro) { // todo // php redis.php $pro->exec("/home/work/study/soft/php/bin/php", [__DIR__.'/../server/http_server.php']); }, false); $pid = $process->start(); echo $pid . PHP_EOL; swoole_process::wait();
process實例:
<?php class BaseProcess{ private $process; public function __construct() { $this->process = new swoole_process([$this,'run'],false,true); $this->process->start(); swoole_event_add($this->process->pipe,function($pipe){ $data = $this->process->read(); echo 'RECV: '.$data.PHP_EOL; }); } public function run($worker){ swoole_timer_tick(1000,function($timer_id){ static $index = 0 ; $index += 1; $this->process->write('hello sunlong'); var_dump($index); if($index == 10){ swoole_timer_clear($timer_id); } }); } } new BaseProcess(); swoole_process::signal(SIGCHLD,function($sig){ while($ret = swoole_process::wait(false)){ echo "PID={$ret['pid']}\n"; } });
返回結果
[root@localhost php]# php7 process2.php int(1) RECV: hello sunlong int(2) RECV: hello sunlong int(3) RECV: hello sunlong int(4) RECV: hello sunlong int(5) RECV: hello sunlong int(6) RECV: hello sunlong int(7) RECV: hello sunlong int(8) RECV: hello sunlong int(9) RECV: hello sunlong int(10) RECV: hello sunlong PID=2903
上述案例 建立子進程,而後執行定時器,定時器向管道寫入數據;swoole_event_add監聽管道寫事件回調(異步監聽管道數據),讀取到寫的內容並輸出。
此時程序還沒終止,event loop還在監聽管道數據
下面是消息隊列做爲進程間通訊 消息隊列同步的 不支持異步
[root@localhost php]# php7 process2.php int(1) RECV: hello sunlong int(2) RECV: hello sunlong int(3) RECV: hello sunlong int(4) RECV: hello sunlong int(5) RECV: hello sunlong int(6) RECV: hello sunlong int(7) RECV: hello sunlong int(8) RECV: hello sunlong int(9) RECV: hello sunlong int(10) RECV: hello sunlong
昇華一下 實現簡單的進程池 動態擴展進程池 同時處理更多任務
可是推薦使用swoole_server+task作任務池
swoole_process->exec
process在swoole_server中仍是有實際運用的,好比執行腳本或者shell命令,linux的tail,top,ps持續的命令,經過管道實時監聽,展現在網頁上,作成一個外部監控器(process應用)
task執行一個長耗時任務,
二者有重疊可是也有區別