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执行一个长耗时任务,

二者有重叠可是也有区别

相关文章
相关标签/搜索