运行流程图



当启动一个Swoole应用时,一共会创建2+n+m个进程,2为一个Master进程和一个Manager进程,其中n为Worker进程数,m为TaskWorker进程数。

名词解释

Master进程

主进程,该进程会创建Manager进程、Reactor线程,UDP收包线程,心跳检测线程等线程

Manger进程

管理进程,该进程的作用是创建、管理所有的Worker进程和TaskWorker进程。
  • 子进程结束运行时,manager进程负责回收此子进程,避免成为僵尸进程。并创建新的子进程
  • 服务器关闭时,manager进程将发送信号给所有子进程,通知子进程关闭服务
  • 服务器reload时,manager进程会逐个关闭/重启子进程

Worker进程

工作进程,所有的业务逻辑代码均在此进程上运行。当Reactor线程接收到来自客户端的数据后,会将数据打包通过管道发送给某个Worker进程。
  • 接受由Reactor线程投递的请求数据包,并执行PHP回调函数处理数据
  • 生成响应数据并发给Reactor线程,由Reactor线程发送给TCP客户端
  • 可以是异步非阻塞模式,也可以是同步阻塞模式
  • Worker以多进程的方式运行

TaskWorker进程

一种特殊的工作进程,该进程的作用是处理一些耗时较长的任务,以达到释放Worker进程的目的。
  • 接受由Worker进程通过swoole_server->task/taskwait方法投递的任务
  • 处理任务,并将结果数据返回(使用swoole_server->finish)给Worker进程
  • 完全是同步阻塞模式
  • TaskWorker以多进程的方式运行

Reactor线程

实际运行Linux中是epoll实例,MacOS中为Kqueue实例,用于accept客户端连接以及接收客户端数据。Swoole的主进程是一个多线程的程序。其中有一组很重要的线程,称之为Reactor线程。它就是真正处理TCP连接,收发数据的线程。Swoole的主线程在Accept新的连接后,会将这个连接分配给一个固定的Reactor线程,并由这个线程负责监听此socket。在socket可读时读取数据,并进行协议解析,将请求投递到Worker进程。在socket可写时将数据发送给TCP客户端。
  • 负责维护客户端TCP连接、处理网络IO、处理协议、收发数据
  • 完全是异步非阻塞的模式
  • 全部为C代码,除Start/Shudown事件回调外,不执行任何PHP代码
  • 将TCP客户端发来的数据缓冲、拼接、拆分成完整的一个请求数据包
  • Reactor以多线程的方式运行

运行机制

Swoole是php的扩展,一旦运行后就会接管PHP的控制权,进入事件循环。 当某种IO(网络IO)事件发生时,Swoole 会回调用户设置的指定回调函数。Swoole承担了底层网络事件的监听及各种底层事件处理,当收到请求时,会触发事件提醒,然后将控制权转交预先注册的事件回调函数,来进行后续的处理。可以理解为Reactor就是nginx,Worker就是php-fpm。Reactor线程异步并行地处理网络请求,然后再转发给Worker进程中去处理。Reactor和Worker间通过UnixSocket进行通信。Swoole提供的TaskWorker是一套更完整的方案,将任务的投递、队列、php任务处理进程管理合为一体。通过底层提供的API可以非常简单地实现异步任务的处理。另外TaskWorker还可以在任务执行完成后,再返回一个结果反馈到Worker。Swoole的Reactor、Worker、TaskWorker之间可以紧密的结合起来,提供更高级的使用方式。一个更通俗的比喻,假设Server就是一个工厂,Master是董事长,Manager是CEO,那Reactor就是销售经理,接受客户订单。而Worker就是工人,当销售接到订单后,Worker去工作生产出客户要的东西。而TaskWorker可以理解为行政人员,可以帮助Worker干些杂事,让Worker专心工作。

所谓的回调函数(CallBack) 就好比是张开了夹子的捕鼠器,我们设定当有老鼠踩到捕鼠器的时候,他会关闭夹子然后捉住老鼠,我们放置捕鼠器的时候,捕鼠器并没有真的抓老鼠。这个设定就是回调,他不立刻执行,会在遇到触发条件(事件)时执行,在上面的示例当中我们放置了3个捕鼠器(回调函数),我们只需要知道他会在特定老鼠(事件)踩到的时候(发生的时候)去执行我们期望的功能就好。

  • 底层会为Worker进程、TaskWorker进程分配一个唯一的ID
  • 不同的Worker和TaskWorker进程之间可以通过sendMessage接口进行通信

运行周期

程序全局期

 在swoole_server->start之前就创建好的对象,我们称之为程序全局生命周期。这些变量在程序启动后就会一直存在,直到整个程序结束运行才会销毁。有一些服务器程序可能会连续运行数月甚至数年才会关闭/重启,那么程序全局期的对象在这段时间持续驻留在内存中的。程序全局对象所占用的内存是Worker进程间共享的,不会额外占用内存。这部分内存会在写时分离(COW),在Worker进程内对这些对象进行写操作时,会自动从共享内存中分离,变为进程全局对象。程序全局期include/require的代码,必须在整个程序shutdown时才会释放,reload无效。

进程全局期

 swoole拥有进程生命周期控制的机制,一个Worker子进程处理的请求数超过max_request配置后,就会自动销毁。Worker进程启动后创建的对象(onWorkerStart中创建的对象),在这个子进程存活周期之内,是常驻内存的。onConnect/onReceive/onClose 中都可以去访问它。进程全局对象所占用的内存是在当前子进程内存堆的,并非共享内存。对此对象的修改仅在当前Worker进程中有效。进程期include/require的文件,在reload后就会重新加载。

会话期

 会话期是在onConnect后创建,或者在第一次onReceive时创建,onClose时销毁。一个客户端连接进入后,创建的对象会常驻内存,直到此客户端离开才会销毁。swoole中会话期的对象直接是常驻内存,不需要session_start之类操作。可以直接访问对象,并执行对象的方法。

请求期

 请求期就是指一个完整的请求发来,也就是onReceive收到请求开始处理,直到返回结果发送response。这个周期所创建的对象,会在请求完成后销毁。swoole中请求期对象与普通PHP程序中的对象就是一样的。请求到来时创建,请求结束后销毁。

4种PHP回调函数风格

匿名函数

$server->on('Request', function ($req, $resp) use ($a, $b, $c) {echo "hello world";
});

可使用use向匿名函数传递参数

类静态方法

class A
{static function test($req, $resp){echo "hello world";}
}
$server->on('Request', 'A::Test');
$server->on('Request', array('A', 'Test'));

对象方法

class A
{function test($req, $resp){echo "hello world";}
}$object = new A();
$server->on('Request', array($object, 'test'));

函数

function my_onRequest($req, $resp)
{echo "hello world";
}
$server->on('Request', 'my_onRequest');

编程须知

注意事项

  • 不要在代码中执行sleep以及其他睡眠函数,这样会导致整个进程阻塞
  • 在swoole程序中禁止使用exit/die,如果PHP代码中有exit/die,当前工作的Worker进程、Task进程、User进程、以及swoole_process进程会立即退出。使用exit/die后Worker进程会因为异常退出, 被master进程再次拉起, 最终造成进程不断退出又不断启动和产生大量警报日志。
  • mt_rand随机数,在Swoole中如果在父进程内调用了mt_rand,不同的子进程内再调用mt_rand返回的结果会是相同的。所以必须在每个子进程内调用mt_srand重新播种。
  • while循环的影响,异步程序如果遇到死循环,事件将无法触发。异步IO程序使用Reactor模型,运行过程中必须在reactor->wait处轮询。如果遇到死循环,那么程序的控制权就在while中了,reactor无法得到控制权,无法检测事件,所以IO事件回调函数也将无法触发。
  • 可通过register_shutdown_function来捕获致命错误,在进程异常退出时做一些清理工作
  • PHP代码中如果有异常抛出,必须在回调函数中进行try/catch捕获异常,否则会导致工作进程退出
  • 不支持set_exception_handler,必须使用try/catch方式处理异常
  • Worker进程不得共用同一个Redis或MySQL等网络服务客户端,Redis/MySQL创建连接的相关代码可以放到onWorkerStart回调函数中。

异步编程

  • 异步程序要求代码中不得包含任何同步阻塞操作
  • 异步与同步代码不能混用,一旦应用程序使用了任何同步阻塞的代码,程序即退化为同步模式

类/函数重复定义

 新手非常容易犯这个错误,由于Swoole是常驻内存的,所以加载类/函数定义的文件后不会释放。因此引入类/函数的php文件时必须要使用include_once或require_once,否会发生cannot redeclare function/class 的致命错误。

进程隔离

 进程隔离也是很多新手经常遇到的问题。修改了全局变量的值,为什么不生效,原因就是全局变量在不同的进程,内存空间是隔离的,所以无效。所以使用Swoole开发Server程序需要了解进程隔离问题。
  • 不同的进程中PHP变量不是共享,即使是全局变量,在A进程内修改了它的值,在B进程内是无效的
  • 如果需要在不同的Worker进程内共享数据,可以用Redis、MySQL、文件、SwooleTable、APCu、shmget等工具实现
  • 不同进程的文件句柄是隔离的,所以在A进程创建的Socket连接或打开的文件,在B进程内是无效,即使是将它的fd发送到B进程也是不可用的

swoole入门4-初识swoole相关推荐

  1. Swoole学习-Swoole入门指南

    初识Swoole Swoole官网:https://www.swoole.com/ Swoole官方文档:https://wiki.swoole.com/ 预备相关知识素材推荐 入门书籍:<tc ...

  2. Swoole学习手记(一)初识Swoole

    目录 初识Swoole 创建服务器(上) 创建服务器(下) 异步任务task 持续更新中... 参加工作有一段时间了,偶尔会听到swoole,对我这种PHP小白粗略看下文档都会觉得很牛逼.由于学习成本 ...

  3. Swoole入门指南:PHP7安装Swoole详细教程(一)

    好久未更新了,不是懒呃,是太忙啦!终于偷得浮生几日闲. 这一段时间准备为大家带来swoole的入门教程,感受一下php的nodeJs强悍之处. 所有的示例代码均放在了github上:learn-swo ...

  4. Swoole入门指南:PHP7安装Swoole详细教程(一) 1

    这里不在使用apache做为web server.该用nginx + php-fpm,性能更强大,配置更方便.并且为了跟上php的步伐,也使用了比较新的php版本 [x] centos7 [x] ph ...

  5. php的swoole教程,PHP + Swoole2.0 初体验(swoole入门教程)

    PHP + Swoole2.0 初体验(swoole入门教程) 环境:centos7 + PHP7.1 + swoole2.0 准备工作: 一. swoole 扩展安装 1 .下载swoole cd/ ...

  6. swoole php 使用教程,Swoole 扩展安装与使用入门

    Swoole 扩展安装与使用入门 由 学院君 创建于2年前, 最后更新于 1年前 版本号 #3 37642 views 13 likes 5 collects Swoole 概述 Swoole 是面向 ...

  7. Swoole入门教程

    Swoole入门教程第1季:主要讲解Swoole开发文档中入门指引中部分内容. 视频在线观看:https://ke.qq.com/course/319587?saleToken=90851 转载于:h ...

  8. Swoole入门到实战

      收集整理的一套 Swoole入门到实战 打适php高性能直播的视频教程!分享给大家,真实有效! 收集不易且用且珍惜!

  9. Swoole入门教程第1季

    Swoole入门教程第1季:主要讲解Swoole开发文档中入门指引中部分内容. 视频在线观看:https://ke.qq.com/course/319587

最新文章

  1. linux内存实际占用分析
  2. tkinter实现滚动文本框
  3. vba调用计算机,如何实现跨工作表自动引用数据? 求:EXCEL公式(函数)或VBA宏程序...
  4. 大一新生开发的小工具火了,网友:我好菜
  5. Nginx四层负载均衡模块添加
  6. git clone报错:fatal: unable to access ‘https://github.com/...
  7. OpenShift 4 Tekton - Tekton实现包含Gogs+SonaQube+Nexus+Report+WebHook的Pipeline
  8. jar k8s 自己的 部署_怎样部署K8S服务器
  9. java中class.forName(str)的作用
  10. ADI公司与B-Secur携手开发面向汽车工业的生物特征识别技术
  11. java 文件图标_如何用java程序修改文件夹默认图标,麻烦了
  12. 小白不知道raw批量转换jpg怎么转?分享好用的方法
  13. 为了理想,因为爱情-开课第一天有感(鸡汤向)
  14. oracle数据库课程描述,《ORACLE数据库简介》课件.ppt
  15. 爱普生Epson Artisan 800 一体机驱动
  16. python 时间格式datetime、str与date的相互转换
  17. PDF转图片软件有什么?建议收藏这三款软件
  18. 怎么可以修改pr基本图形中的文字_10、Pr中基本图形安装使用,点点就可以应用高级的字幕...
  19. 邮购了正版蓝光碟《CODEnbsp;GEASS叛逆…
  20. 域,域名,同域,跨域及解决

热门文章

  1. 强大的修图app--美图秀秀
  2. s3c2440 LCD驱动,USB驱动,触摸屏以及ADC驱动移植
  3. 【sql的mapper.xml文件】完美去除idea中mapper.xml文件中的黄色绿色背景色
  4. java URL中含有汉字转码格式
  5. 马哲法科的jQuery
  6. Spring配置数据源没有maxActive和maxWait参数解决方法
  7. win10 开机自动清理垃圾
  8. 如何增肥,变成肌肉男【转】
  9. MachineKey
  10. OGG|Oracle GoldenGate 基础