更多内容,欢迎关注微信公众号:全菜工程师小辉~php
过去一年使用PHP和Java两种技术栈完成了一个游戏服务器项目。因为项目中有高频的网络请求,因此PHP技术栈尝试使用Swoole引擎(基于事件的高性能异步并行网络通讯引擎)来完成部分游戏业务。nginx
安装swoole很简单,因为是国人作的项目,不少issue能够在官网文档找到答案。安装分两种:git
具体操做百度一下便可,网上相关内容不少。
Swoole运行的流程图以下:github
结构图以下:数据库
Swoole引擎分为两种模式:单线程模式和进程模式。本文只讨论进程模式。具体二者区别官方文档中有说明。
用于处理swoole核心事件,好比来自客户端的链接,本地通信的管道。master进程里有多个线程,每一个线程运行了一个epol函数的实例。(因为Worker进程并非由Master进程fork出来的,因此可能会出现强行kill Master进程后,Worker进程依旧存在)apache
Swoole的主进程是一个多线程的程序。其中有一组很重要的线程,称之为Reactor线程。它就是真正处理TCP链接,收发数据的线程。
Swoole的主线程在Accept新的链接后,会将这个链接分配给一个固定的Reactor线程,并由这个线程负责监听此socket。在socket可读时读取数据,并进行协议解析,将请求投递到Worker进程。在socket可写时将数据发送给TCP客户端编程
swoole中worker/task进程都是由Manager进程Fork并管理的。
子进程结束运行时,manager进程负责回收此子进程,避免成为僵尸进程。并建立新的子进程
服务器关闭时,manager进程将发送信号给全部子进程,通知子进程关闭服务
服务器reload时,manager进程会逐个关闭/重启子进程segmentfault
Swoole提供了完善的进程管理机制,当Worker进程异常退出,如发生PHP的致命错误、被其余程序误杀,或达到max_request次数以后正常退出。主进程会从新拉起新的Worker进程。 Worker进程内能够像普通的apache+php或者php-fpm中写代码。不须要像Node.js那样写异步回调的代码。缓存
Master内的回调函数:服务器
Worker进程内的回调函数
TaskWorker进程内的回调函数
Manager进程内的回调函数
能够理解为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接口进行通讯。
该项目开发阶段使用的swoole引擎版本1.9.6,后来因为测试环境安装成了4.3.2版本,因此尝试业务代码做调整。不过swoole的向下兼容很值得佩服的是,这过程当中居然只发现了一处代码不兼容的问题:是有关swoole_server的一项配置参数,在原来版本采用了魔鬼数字进行配置的,可是到新版本,这个数字没有被宏定义,后来经过查看swoole源码找到了宏定义组,而后修改了这处配置。(不过版本升级顺利也是基于swoole的业务代码比较少,因此仅供参考)