先了解一下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执行一个长耗时任务,
二者有重叠可是也有区别