Swoole引擎原理的快速入门干货
过去半年使用PHP和Java两种技术栈完成了一个游戏服务器专案。由于专案中有高频的网络请求,所以PHP技术栈尝试使用Swoole引擎(基于事件的高效能异步并行网络通讯引擎)来完成部分游戏业务。
Swoole的安装
安装swoole很简单,由于是国人做的专案,很多issue可以在官网文件找到答案。安装分两种:编译安装。直接去github或者gitee去下载官方的发行版,编译安装后,将so拓展写入php.ini档案。容器安装。swoole引擎应用广泛,所以hub上有很多可用的容器,选择需要的pull一下即可。具体操作百度一下即可,网上相关内容很多。
Swoole引擎的优势
常驻内存。传统 PHP框架或者单档案,在处理每个请求之前,都要做一遍载入框架档案、配置的操作,请求完成之后会释放所有资源和内存,无须担心内存泄漏。但是如果请求数量上升,并发很高的时候,快速建立资源,又马上释放,会导致 PHP 程式执行效率急剧下降。而使用 Swoole 则没有这个问题:PHP的程式码载入到内存后,拥有更长的生命周期,这样建立的数据库连线和其他大的物件,不被释放。每次请求只需要处理很少的程式码,而这些程式码只在第一次执行时,被 PHP 解析器编译,驻留内存。以后都是直接载入 OPCODE ,让 Zend 引擎直接执行。另外,之前PHP不能实现的,如数据库连线池,快取连线池都可以在Swoole引擎下实现。系统的执行效率会大大提高。快速开发。Swoole引擎提供了PHP语言的异步多执行绪服务器,异步TCP/UDP网络客户端,异步MySQL,异步Redis,数据库连线池,AsyncTask,讯息伫列,毫秒定时器,异步档案读写,异步DNS查询。 Swoole内建了Http/WebSocket服务器端/客户端、Http2.0服务器端。协程程式设计模式。Swoole4可以使用完全同步的程式码实现异步程式。PHP程式码无需额外增加任何关键词,底层自动进行协程排程,实现异步IO。Swoole引擎的流程解析
Swoole执行的流程图如下:
Swoole的执行图
Swoole中的执行绪或程序
结构图如下:

Swoole的执行绪图
Swoole引擎分为两种模式:单执行绪模式和程序模式。本文只讨论程序模式。具体两者区别官方文件中有说明。
Master程序
用于处理swoole核心事件,比如来自客户端的连线,本地通讯的管道。master程序里有多个执行绪,每个执行绪运行了一个epol函式的例项。(由于Worker程序并不是由Master程序fork出来的,所以可能会出现强行kill Master程序后,Worker程序依旧存在)
Reactor执行绪
Swoole的主程序是一个多执行绪的程式。其中有一组很重要的执行绪,称之为Reactor执行绪。它就是真正处理TCP连线,收发资料的执行绪。
Swoole的主执行绪在Accept新的连线后,会将这个连线分配给一个固定的Reactor执行绪,并由这个执行绪负责监听此socket。在socket可读时读取资料,并进行协议解析,将请求投递到Worker程序。在socket可写时将资料传送给TCP客户端
Manager程序
swoole中worker/task程序都是由Manager程序Fork并管理的。
子程序结束执行时,manager程序负责回收此子程序,避免成为僵尸程序。并建立新的子程序
服务器关闭时,manager程序将传送讯号给所有子程序,通知子程序关闭服务
服务器reload时,manager程序会逐个关闭/重启子程序
Worker程序
Swoole提供了完善的程序管理机制,当Worker程序异常退出,如发生PHP的致命错误、被其他程式误杀,或达到max_request次数之后正常退出。主程序会重新拉起新的Worker程序。 Worker程序内可以像普通的apache+php或者php-fpm中写程式码。不需要像Node.js那样写异步回拨的程式码。
各程序的回拨函式
Master内的回拨函式:
onStartonShutdownWorker程序内的回拨函式
onWorkerStartonWorkerStoponConnectonCloseonReceiveonFinishTaskWorker程序内的回拨函式
onTaskonWorkerStartManager程序内的回拨函式
onManagerStartonManagerStopReactor、Worker、TaskWorker的关系
可以理解为Reactor就是nginx,Worker就是php-fpm。Reactor执行绪异步并行地处理网络请求,然后再转发给Worker程序中去处理。Reactor和Worker间通过UnixSocket进行通讯。
在php-fpm的应用中,经常会将一个任务异步投递到Redis等伫列中,并在后台启动一些php程序异步地处理这些任务。Swoole提供的TaskWorker是一套更完整的方案,将任务的投递、伫列、php任务处理程序管理合为一体。通过底层提供的API可以非常简单地实现异步任务的处理。另外TaskWorker还可以在任务执行完成后,再返回一个结果反馈到Worker。
Swoole的Reactor、Worker、TaskWorker之间可以紧密的结合起来,提供更高阶的使用方式。一个更通俗的比喻:假设Swoole应用服务器是一个工厂,那Reactor就是销售,接受客户订单。而Worker就是工人,当销售接到订单后,Worker去工作生产出客户要的东西。而TaskWorker可以理解为行政人员,可以帮助Worker干些杂事,让Worker专心工作。
底层会为Worker程序、TaskWorker程序分配一个唯一的ID。不同的Worker和TaskWorker程序之间可以通过sendMessage界面进行通讯。
实际专案中的各程序执行绪的分工:
Manager程序:负责管理worker程序,建立或回收Worker程序:游戏逻辑处理taskWorker程序:向客户端发网络包、关闭长期不活跃的tcp连线Swoole版本相容性
该专案开发阶段使用的swoole引擎版本1.9.6,后来由于测试环境安装成了4.3.2版本,所以尝试业务程式码作调整。不过swoole的向下相容很值得佩服的是,这过程中竟然只发现了一处程式码不相容的问题:是有关swoole_server的一项配置引数,在原来版本采用了魔鬼数字进行配置的,但是到新版本,这个数字没有被宏定义,后来通过检视swoole源代码找到了宏定义组,然后修改了这处配置。(不过版本升级顺利也是基于swoole的业务程式码比较少,所以仅供参考)
更多内容,欢迎关注微信公众号:全菜工程师小辉~