摘要:简介Swoole是一个PHP扩展,提供了PHP语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,异步Redis,数据库连接池,AsyncTask,消息队列,毫秒定时器,异步文件读写,异步DNS查询。 Swoole内置了Http/WebSo ...
简介
Swoole是一个PHP扩展,提供了PHP语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,异步Redis,数据库连接池,AsyncTask,消息队列,毫秒定时器,异步文件读写,异步DNS查询。 Swoole内置了Http/WebSocket服务器端/客户端、Http2.0服务器端。
Swoole: PHP的异步、并行、高性能网络通信引擎
http://www.swoole.com/
Github:
https://github.com/swoole
https://github.com/matyhtf
安装
Swoole需要使用源码安装。暂无Windows版扩展。
源码安装
wget -O swoole.zip https://github.com/swoole/swoole-src/archive/v1.9.11.zipunzip swoole.zipcd swoole phpize ./configure make && make install
pecl安装
由于pecl是需要编译的,所以需要先安装编译器(已安装编译器可以忽略):
yum install -y gcc gcc-c++ make cmake bison autoconf
然后:
pecl install swoolepecl install redis
pecl安装扩展完成后会提示添加so文件到php.ini。示例:
Build process completed successfully Installing '/usr/lib64/php/modules/swoole.so'install ok: channel://pecl.php.net/swoole-1.9.11configuration option "php_ini" is not set to php.ini location You should add "extension=swoole.so" to php.ini
添加示例:
[swoole]extension = /usr/lib64/php/modules/swoole.so
版本选择
建议使用的版本(截止时间2017-6-3)
稳定版:v1.9.9预览版:v2.0.7
1.9.x
分支已进入特性锁定期,不再开发新功能,仅修复BUG。
最低版本:
建议1.8.6+
。PHP7建议使用1.9.2+
。
建议使用的PHP版本
PHP5.5或更高版本PHP7.0.13或更高版本
使用TP3.1+
框架的朋友升级到PHP7.1.0
可能会出现rewrite失效问题。建议PHP7.0.x
系列。
快速查看当前swoole的版本:
php --ri swoole
1.8.6~1.8.13
都是小范围BUG修复及功能新增。其中 1.8.11
增加SIGRTMIN信号处理函数,用于重新打开日志文件。
1.8.6
版本是一个重要的BUG修复版本,主要修复了PHP7环境下HttpServer、TCPClient、HttpClient、Redis等客户端存在的内存泄漏、崩溃问题。
1.9.0
版本增加了多项新特性,修复了多个已知问题。1.9版本是100%向下兼容1.8的,用户可无缝升级。
1.9.1
修复PHP7下启用opcache导致崩溃的问题;重构reopen log file
特性,收到SIGRTMIN
信号后重新打开日志文件并重定向标准输出 等。
1.9.2
修复PHP7下发生zend_mm_heap corrupted
的问题 等。
1.9.4
修复WebSocket服务器默认onRequest方法内存泄漏问题 等。
1.9.5
增加pid_file选项,在Server启动时将主进程ID写入指定的文件 等。
1.9.6
修复添加超过1万个以上定时器时发生崩溃的问题;增加swoole_serialize模块,PHP7下高性能序列化库;修复监听UDP端口设置onPacket无效的问题 等。
1.9.9
修复Http2客户端POST数据时协议错误问题 等。
1.9.11
修复WebSocket服务器onOpen回调函数存在内存泄漏的问题;修复Http服务器文件上传在5.6版本发生崩溃的问题;优化添加Task和Timer的定时器性能,提升分支预测成功率 等。
Swoole的进程模型
运行模式
Swoole目前总共有三种运行模式,默认为多进程模式(SWOOLE_PROCESS
)。
# Base模式(SWOOLE_BASE)传统的异步非阻塞Server,reactor和worker是同一个角色。TCP连接是在worker进程中维持的。 如果客户端连接之间不需要交互,可以使用BASE模式。如Memcache、Http服务器等。# 线程模式多线程Worker模式,Reactor线程来处理网络事件轮询,读取数据。得到的请求交给Worker线程去处理。 缺点:一个线程发生内存错误,整个进程会全部结束。 由于PHP的ZendVM在多线程模式存在内存错误,多线程模式在v1.6.0版本后已关闭。# 进程模式与多线程Worker模式不同的是,线程换成了进程。Reactor线程来处理网络事件轮询,读取数据。得到的请求交给Worker进程去处理。适合业务逻辑非常复杂的场景。如WebSocket服务器等。
$serv = new swoole_server(string $host, int $port, int $mode = SWOOLE_PROCESS, int $sock_type = SWOOLE_SOCK_TCP);
实例分析
我们来使用实例进行分析:
$server = new swoole_server("127.0.0.1",8088);//默认是多进程模式、TCP类型$server->on('connect', function ($serv, $fd){ }); $server->on('receive', function ($serv, $fd, $from_id, $data){ }); $server->on('close', function ($serv, $fd){ }); $server -> start();
继续在Shell中输入以下命令:
php swoole_tcp_server.php pstree -ap|grep swoole_tcp_server | | `-php,2454 swoole_tcp_server.php | | |-php,2456 swoole_tcp_server.php | | | `-php,2458 swoole_tcp_server.php
从系统的输出中,我们可以很容看出server其实有3个进程,进程的pid分别是2454、2456、2458,其中2454是2456的父进程,而2456又是2458的父进程。
所以,其实我们虽然看起来只是启动了一个Server,其实最后产生的是三个进程。
这三个进程中,所有进程的根进程(2454),就是所谓的Master
进程;而2456进程,则是Manager
进程;最后的2458进程,是Worker
进程。
基于此,我们简单梳理一下,当执行的start方法之后,发生了什么:
守护进程模式下,当前进程fork出Master进程,然后退出,Master进程触发OnMasterStart事件。
Master进程启动成功之后,fork出Manager进程,并触发OnManagerStart事件。
Manager进程启动成功时候,fork出Worker进程,并触发OnWorkerStart事件。
非守护进程模式下,则当前进程直接作为Master进程工作。
所以,一个最基础的Swoole Server,至少需要有3个进程,分别是Master进程、Manager进程和Worker进程。
事实上,一个多进程模式下的Swoole Server中,有且只有一个Master进程;有且只有一个Manager进程;却可以有n个Worker进程。
进程模型
Master
进程是一个多线程进程,其中有一组非常重要的线程,叫做Reactor
线程(组),每当一个客户端连接上服务器的时候,都会由Master进程从已有的Reactor线程中,根据一定规则挑选一个,专门负责向这个客户端提供维持链接、处理网络IO与收发数据等服务。分包拆包等功能也是在这里完成。
Manager
进程,某种意义上可以看做一个代理层,它本身并不直接处理业务,其主要工作是将Master进程中收到的数据转交给Worker进程,或者将Worker进程中希望发给客户端的数据转交给Master进程进行发送。
Manager
进程还负责监控Worker进程,如果Worker进程因为某些意外挂了,Manager进程会重新拉起新的Worker进程,有点像Supervisor的工作。而这个特性,也是最终实现热重载的核心机制。
Worker
进程其实就是处理各种业务工作的进程,Manager将数据包转交给Worker进程,然后Worker进程进行具体的处理,并根据实际情况将结果反馈给客户端。
我们可以总结出来上面简单的Server,当客户端连接的时候这个过程中,三种进程之间是怎么协作的:
Client主动Connect的时候,Client实际上是与Master进程中的某个Reactor线程发生了连接。
当TCP的三次握手成功了以后,由这个Reactor线程将连接成功的消息告诉Manager进程,再由Manager进程转交给Worker进程。
在这个Worker进程中触发了OnConnect的方法。
当Client向Server发送了一个数据包的时候,首先收到数据包的是Reactor线程,同时Reactor线程会完成组包,再将组好的包交给Manager进程,由Manager进程转交给Worker。
此时Worker进程触发OnReceive事件。
如果在Worker进程中做了什么处理,然后再用Send方法将数据发回给客户端时,数据则会沿着这个路径逆流而上。
Swoole进程/线程结构图:
现在,我们基于上面的例子修改代码,来看看一个简单的多进程Swoole Server的几个基本配置:
$server->set(array( 'demonize' => false,//是否后台运行 'reactor_num' => 2, 'worker_num' => 4)); $server -> start();
reactor_num
:表示Master进程中,Reactor线程总共开多少个,注意,这个可不是越多越好,因为计算机的CPU是有限的,所以一般设置为与CPU核心数量相同,或者两倍即可。
友情提示:垃圾评论一律封号 加我微信:826096331拉你进VIP群学习群