遵从硬件不行软件来凑,出现了各种压榨CPU干活的异步编程技术。进程生死,一般遵循谁生谁管,当然儿子出问题(退出),会被告知老爸。没了爸了孩子(子进程)会被特殊进程收编。异步编程,通常是想好退路,被动的给别人执行。本文只是介绍一些与swoole相关的概念性的内容。
缘起
nodejs中称之为回调地狱,解决这种回调金字塔主要有以下几种方案
EventProxy 事件发布订阅模式
BlueBird Promise方案 (基本上是将嵌套调用变为水平调用)
Async 异步流程控制库
select,poll,epoll,kqueue 之类的C事件库
epoll 可以维持无限数量的连接,而且无需轮询
select,poll 面临 循环检测连接是否有事件,假定只有一个连接可用,循环就极大浪费CPU (C10k问题出现)
生成器
ES6原生有,python有,当然php也有,特点是需要显性的使用 yield 关键字
具备现场保存与返场的能力,让渡控制权 (与此类似C的万恶 goto 一样,跳来跳去)
异步/同步/阻塞/非阻塞
异/同步 与 阻塞 非阻塞 其实是站在 不同的角度上对同一事件的描述。
前者侧重是生产者如何拿到结果,后者则关注是消费者否可做其他的事。
白话就是,同步与异步关注你能不能等,能等就是异步,不能等现在立刻马上就要则是同步。非阻塞与阻塞,则是指你当前能不能做别的。后者出现的情况,常在当前的任务有依赖条件,没有了谁谁就不能继续进行,因此需要阻塞。而前者,则不一样,谁先谁后没关系,也不关心怎么来的,只要结果,当然这种情况下要求任务独立无依赖。
进程
进程本身不是基本的运行单位,而是线程的容器
具有动态性,并发性,异步性,结构性
独立性 与其他进程隔离
结构性 拥有代码段,数据段,PCB(进程控制块,包含进程的描述和控制信息)
父子进程
fork() 在当前进程创建一个新进程
exec() 切换子进程中的执行程序
正常情况下,父进程会收到两个返回值
exit 退了
wait 获取子进程的退出状态,内核从内存中释放已结束子进程的PCB
父子进程,也就一个 fork 生了,因此如果是原生php fork完毕,在子进程时pid 为0 (特别是通过循环产生子fork进程)时,需要且必须执行exit让子进程断子绝孙,否则子子孙孙无穷尽也....
组长/会话进程
setpgid() 加入一个现有的进程组或创建一个新进程组
setsid 非组长进程建立新会话,该会话进程成为新组长进程
每个进程被创建时,它便会成为父进程在session中的一员
session主要是针对一个tty终端建立(与守护进程相关,因此守护进程的sessionid通常不能同终端一样)
在*unix中,组长进程不能创建会话,简单理解就是在组长进程中,执行setsid函数会报错
Linux特殊进程
0 调度进程,交换进程,系统进程
1 init 进程,内核调用,没有终端限制
swoole进程组件
Master进程
swoole 应用的root进程,fork 出 Reactor线程和Manager进程
Reactor 是包含在 Master 进程中的多线程程序,处理 TCP 连接和数据收发(异步非阻塞方式)
Manager进程
Manager 进程负责 fork 并维护多个 Worker 子进程,负责回收并创建新的 Worker 子进程
当服务器关闭时,Manager 将发送信号给所有 Worker 子进程,通知其关闭服务
Worker进程
以多进程方式运行,负责接受由 Reactor 线程投递的请求数据包
执行 PHP 回调函数,生成响应数据并发给 Reactor 线程
Task Worker进程
同上,但仅用于任务分发,Task Worker 负责从队列中消费(同步阻塞方式处理)任务
swoole组件概念关系图
swoole官方经典话术
Swoole 官方对 Reactor、Worker、Task Worker有一个形象的比喻,如果把基于 Swoole 的 Web 服务器比作一个工厂,那么 Reactor 就是这个工厂的销售员,Worker 是负责生产的工人,销售员负责接订单,然后交给工人生产,而 Task Worker 可以理解为行政人员,负责提工人处理生产以外的杂事,比如订盒饭、收快递,让工人可以安心生产。
本作品采用《CC 协议》,转载必须注明作者和本文链接