swoole 进程间关系

arch

实例

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 事件图

events

一个请求经历的步骤:

1、服务器主线程等待客户端连接
2、Reactor 线程处理连接 socket,读取 socket 上的请求数据(receive),将请求封装好后投递给 Worker 进程
3、Worker 进程就是逻辑单元,处理业务数据
4、Worker 进程结果返回给 Reactor 线程
5、Reactor 线程将结果写回 socket(Send)

所以,跟客户端交互的其实是 Reactor 线程,Reactor 线程作为沟通客户端跟后端的中介。