实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| ➜ ~ ps aux | grep laravels | grep -v grep root 29239 0.0 0.1 989924 42660 ? Sl 11:07 0:03 laravels: master process root 29250 0.0 0.0 402248 23060 ? S 11:07 0:00 laravels: manager process root 29259 0.0 0.5 635160 188684 ? S 11:07 0:06 laravels: worker process 0 root 29260 0.0 0.5 635148 192564 ? S 11:07 0:13 laravels: worker process 1 root 29261 0.0 0.5 633112 189896 ? S 11:07 0:10 laravels: worker process 2 root 29262 0.0 0.5 641240 194080 ? S 11:07 0:19 laravels: worker process 3 root 29263 0.0 0.5 620484 171616 ? S 11:07 0:11 laravels: worker process 4 root 29264 0.0 0.4 588592 146464 ? S 11:07 0:05 laravels: worker process 5 root 29265 0.0 0.4 512808 139264 ? S 11:07 0:03 laravels: worker process 6 root 29266 0.0 0.4 592672 145852 ? S 11:07 0:03 laravels: worker process 7 root 29267 0.0 0.3 551456 102340 ? S 11:07 0:04 laravels: worker process 8 root 29268 0.0 0.5 633128 186340 ? S 11:07 0:05 laravels: worker process 9 root 29269 0.0 0.2 537124 90532 ? S 11:07 0:04 laravels: worker process 10 root 29270 0.0 0.4 590644 147988 ? S 11:07 0:02 laravels: worker process 11 root 29271 0.0 0.2 526872 79992 ? S 11:07 0:05 laravels: worker process 12 root 29272 0.0 0.6 645412 197672 ? S 11:07 0:11 laravels: worker process 13 root 29273 0.0 1.3 904576 452132 ? S 11:07 0:15 laravels: worker process 14 root 29274 0.0 0.3 545384 101540 ? S 11:07 0:04 laravels: worker process 15
➜ ~ pstree -pa 29239 php,29239 // master 进程 ├─php,29250 // manager 进程 │ ├─php,29259 // worker 0 │ ├─php,29260 // worker 1 │ ├─php,29261 // worker 2 │ ├─php,29262 // worker 3 │ ├─php,29263 // worker 4 │ ├─php,29264 // worker 5 │ ├─php,29265 // worker 6 │ ├─php,29266 // worker 7 │ ├─php,29267 // worker 8 │ ├─php,29268 // worker 9 │ ├─php,29269 // worker 10 │ ├─php,29270 // worker 11 │ ├─php,29271 // worker 12 │ ├─php,29272 // worker 13 │ ├─php,29273 // worker 14 │ └─php,29274 // worker 15 ├─{php},29251 // {php} 开头的都是 Master 里创建的线程,这里有 8 个 ├─{php},29252 ├─{php},29253 ├─{php},29254 ├─{php},29255 ├─{php},29256 ├─{php},29257 └─{php},29258
|
我们可以看到,Master 进程是多线程的,但是 Worker 是单线程的。
Master 进程
是一个多线程的程序。其中有一组很重要的线程,称之为 Reactor
线程。它就是真正处理 TCP 连接,收发数据的线程。
多线程使用 pthread 线程库。
Manager 进程
Manager 进程由 Master 进程 fork。
管理 Worker/Task Worker 进程,Worker/Task Worker 进程都是由 Manager
进程 fork 并管理的。
- 子进程结束运行时,manager
进程负责回收此子进程,避免称为僵尸进程。并创建新的子进程。
- 服务器关闭时(swoole server),manager
进程将发信号给所有子进程,通知子进程关闭服务。
- 服务器 reload 时(swoole server),manager
进程会逐个关闭/重启子进程。
为什么不是 Master 进程呢,主要原因是 Master
进程是多线程的,不能安全的执行 fork 操作。
Reactor 线程
主线程(Master 进程)在 accept
新的连接后,会将这个连接分配给一个固定的 Reactor
线程,并由这个线程负责监听此 socket。在 socket
可读时读取数据,并进行协议解析,将请求投递到 Worker 进程。
- 负责维护 TCP 连接、处理网络 IO、处理协议、收发数据。
- 完全是异步非阻塞的模式
- 除 Start/Shutdown 事件回调外,不执行任何 PHP 代码
- 将 TCP 客户端发来的数据缓冲、拼接、拆分成完整的一个请求数据包
- Reactor 以多线程的方式运行
分配的计算方式是 fd % serv->reactor_num
Worker 进程
类似于 php-fpm 进程。
- 接受由 Reactor 线程投递的请求数据包,并执行 PHP
回调函数处理数据。
- 生成响应数据并发给 Reactor 线程,由 Reactor 线程发送给 TCP
客户端
- 可以是异步模式,也可以是同步模式
- Worker 以多进程的方式进行
关系
可以理解为 Reactor 就是 nginx,Worker 就是 php-fpm。Reactor
线程异步并行地处理网络请求,然后再转发给 Worker
进程中去处理(在回调函数中处理)。Reactor 和 Worker 间通过 UnixSocket
进行通信。
一个更通俗的比喻,假设 Server 就是一个工厂,那 Reactor
就是销售,接受客户订单。而 Worker 就是工人,当销售接到订单后,Worker
去工作生产出客户要的东西。而 Task Worker 可以理解为行政人员,可以帮助
Worker 干些杂事,让 Worker 专心工作。
Reactor
它要求主线程(I/O
处理单元)只负责监听文件描述符上是否有事件发生,有的话就立即将该事件通知工作线程/进程(逻辑单元)。除此之外,主线程不做任何其他工作。读写数据,接受新的连接,以及处理客户请求均在工作线程中完成。
swoole 事件图
一个请求经历的步骤:
1、服务器主线程等待客户端连接 2、Reactor 线程处理连接 socket,读取
socket 上的请求数据(receive),将请求封装好后投递给 Worker 进程
3、Worker 进程就是逻辑单元,处理业务数据 4、Worker 进程结果返回给
Reactor 线程 5、Reactor 线程将结果写回 socket(Send)
所以,跟客户端交互的其实是 Reactor 线程,Reactor
线程作为沟通客户端跟后端的中介。