• Event Loop and Process


     先了解一下process和event loop

    EventLoop

    除了异步ServerClient库之外,Swoole扩展还提供了直接操作底层epoll/kqueue事件循环的接口。可将其他扩展创建的socketPHP代码中stream/socket扩展创建的socket等加入到SwooleEventLoop中。

    事件优先级

    1. 通过Process::signal设置的信号处理回调函数
    2. 通过Event::defer设置的延迟执行函数
    3. 通过Timer::tickTimer::after设置的定时器回调函数
    4. 通过Event::cycle设置的周期回调函数

    swoole_event_add函数用于将一个socket加入到底层的reactor事件监听中。此函数可以用在ServerClient模式下

    参数

    参数1可以为以下四种类型:

    • 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可读时回调指定的函数。

    参数4为事件类型的掩码,可选择关闭/开启可读可写事件,如SWOOLE_EVENT_READSWOOLE_EVENT_WRITE,或者SWOOLE_EVENT_READ | SWOOLE_EVENT_WRITE

    在 Server 程序中使用时,必须在 Worker 进程启动后使用。在 Server::start 之前不得调用任何异步 IO 接口

     

    在fpm当中一个请求结束了线程就被关掉了,注册的事件就不会再去监听了

    event lop实例:

    命令符聊天室

    主要应用点:

    异步读取来自副武器的数据

    异步读取来自终端的输入

    手动退出聊天室

     

    监听服务器的读和写操作 

    服务端是不会挺停止的

    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']}
    ";
        }
    });

    返回结果

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

    两者有重叠但是也有区别

  • 相关阅读:
    贪婪匹配
    洛谷P1219 [USACO1.5]八皇后 Checker Challenge【搜索回溯】
    【数据结构笔记】栈
    数据结构课堂笔记
    DAY1
    小记2020.1.10
    c++复习
    c++用流控制成员函数输出数据
    c++用控制符控制输出格式
    "中国东信杯"广西大学第二届程序设计竞赛E Antinomy与红玉海(二分)
  • 原文地址:https://www.cnblogs.com/sunlong88/p/8999348.html
Copyright © 2020-2023  润新知