Event IO Process

 先了解一下process和event loopphp

EventLoop

除了異步ServerClient庫以外,Swoole擴展還提供了直接操做底層epoll/kqueue事件循環的接口。可將其餘擴展建立的socketPHP代碼中stream/socket擴展建立的socket等加入到SwooleEventLoop中。react

事件優先級

  1. 經過Process::signal設置的信號處理回調函數
  2. 經過Event::defer設置的延遲執行函數
  3. 經過Timer::tickTimer::after設置的定時器回調函數
  4. 經過Event::cycle設置的週期回調函數

swoole_event_add函數用於將一個socket加入到底層的reactor事件監聽中。此函數能夠用在ServerClient模式下linux

參數

參數1能夠爲如下四種類型:redis

  • int,就是文件描述符,包括swoole_client->$sockswoole_process->$pipe或者其餘fd
  • stream資源,就是stream_socket_client/fsockopen建立的資源
  • sockets資源,就是sockets擴展中socket_create建立的資源,須要在編譯時加入 ./configure --enable-sockets
  • objectswoole_processswoole_client,底層自動轉換爲管道或客戶端鏈接的socket

參數2爲可讀回調函數,參數3爲可寫事件回調,能夠是字符串函數名、對象+方法、類靜態方法或匿名函數,當此socket可讀時回調指定的函數。shell

參數4爲事件類型的掩碼,可選擇關閉/開啓可讀可寫事件,如SWOOLE_EVENT_READSWOOLE_EVENT_WRITE,或者SWOOLE_EVENT_READ | SWOOLE_EVENT_WRITE編程

在 Server 程序中使用時,必須在 Worker 進程啓動後使用。在 Server::start 以前不得調用任何異步 IO 接口

 

在fpm當中一個請求結束了線程就被關掉了,註冊的事件就不會再去監聽了服務器

event lop實例:swoole

命令符聊天室php7

主要應用點:curl

異步讀取來自副武器的數據

異步讀取來自終端的輸入

手動退出聊天室

 

監聽服務器的讀和寫操做 

服務端是不會挺中止的

process

PHP自帶的pcntl,存在不少不足,如

  • pcntl沒有提供進程間通訊的功能
  • pcntl不支持重定向標準輸入和輸出
  • pcntl只提供了fork這樣原始的接口,容易使用錯誤
  • swoole_process提供了比pcntl更強大的功能,更易用的API,使PHP在多進程編程方面更加輕鬆。

swoole_process提供了以下特性:

  • swoole_process提供了基於unixsock的進程間通訊,使用很簡單隻需調用write/read或者push/pop便可
  • swoole_process支持重定向標準輸入和輸出,在子進程內echo不會打印屏幕,而是寫入管道,讀鍵盤輸入能夠重定向爲管道讀取數據
  • 配合swoole_event模塊,建立的PHP子進程能夠異步的事件驅動模式
  • swoole_process提供了exec接口,建立的進程能夠執行其餘程序,與原PHP父進程之間能夠方便的通訊

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執行一個長耗時任務,

二者有重疊可是也有區別

相關文章
相關標籤/搜索