PHP-FPM 进程模型
我们先来看一下 PHP-FPM 是怎么运行的:
①:发起一个 HTTP 请求。
②:Nginx 转发用户的请求到 PHP-FPM:
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi_params;
}
这里就是将以 .php 结尾的请求转发到本地 9000 端口,而 9000 端口是 PHP-FPM 默认监听端口。
③:PHP-FPM 工作模式:
Master 进程启动 Worker Pool, Worker Pool 维护多个 Worker 进程, Worker 进程负责监听请求并建立连接,并且实现了 fastcgi 协议来通信获取数据,通过嵌入的 PHP 解释器来执行 PHP 脚本。
`这里每个 Worker 进程是阻塞的方式处理用户的请求,同一个 Worker 同一时间只能处理一个请求,因为硬件资源有限,因此比较难的支持大量的并发,常见的 502 Bad Gateway 就是因为 PHP-FPM 没有可用进程了导致的`
④:将 PHP 执行结果返回给 Nginx。
⑤:Nginx 将数据返回给浏览器。
Swoole 进程模型
在 Swoole 里面,我们通过了解进程模型来理解它是怎么工作的,有两种进程工作模型,分别来了解下:
-
- Swoole 在 SWOOLE_PROCESS 模式下的进程模型
①:Master 进程:我们启动的进程,是一个多线程的进程,内部包含了 MainReactor 线程,Reactor 线程等,同时负责创建 Manager 进程来协助管理其他工作进程,Master 进程主要负责网络通信相关的功能。 (关于网络通信 I/O 的模型选择,在 Unix 网络编程提供了 5 种 I/O 模型,Swoole 使用了 Reactor 模型,它基于 IO multiplexing(多路复用IO)模型实现)
②:MainReactor 线程:负责 Accept 客户端的连接,并且将此连接分配给负载低的 Reactor 线程处理。
③:Reactor 线程:负责维护客户端 TCP 连接、处理网络 IO、处理协议、收发数据,将 TCP 客户端发来的数据缓冲、拼接、拆分成完整的一个请求数据包, 并且不执行任何 PHP 代码。(Reactor 线程通过监听 Worker 进程发送给主进程的数据,然后将数据发送给客户端。)。
④:Manager 进程:负责创建 / 回收 worker/task 进程。
⑤:Worker 进程:负责处理 Reactor 线程通过 Unix Socket 投递的请求数据包,(这里编写我们的业务逻辑,执行完成后将数据发送到主进程)。
⑥:Task 进程:负责处理 Worker 进程投递的任务,执行完成后通过onFinish 事件将数据发送给 Worker 进程。
里面涉及到的重点有:
Swoole 内部进程间的 IPC(Inter-Process Communication,进程间通信)使用 Unix Socket 来实现。 Swoole 网络通信 I/O 模型使用 Reactor 模型。
请求处理流程:
❶:客户端发起请求
❷:由 MainReactor 线程建立连接,之后将请求分配给 Reactor 线程, Reactor 线程开始监听到客户端发送的请求数据。
❸:Reactor 线程接收完一个完整请求数据后,将数据发给 Worker 进程处理(数据头部记录了 Reactor 的信息), Worker 进程执行我们的业务逻辑代码,之后将结果通过 Unxi Socket 发送结果给 Master 进程,(数据头部记录了 Reactor 的信息,请求的 fd 信息)。
❹:主进程的每个 Reactor 线程都负责监听 Worker 进程发送的数据包,但是每个 Worker 进程的发送的数据只会由一个 Reactor 线程监听,这里的数据由 Reactor 返回给客户端。(如果是改变连接状态,则找到对应的监听此连接的 Reactor 线程后调用 epoll_ctl)
Swoole 在 SWOOLE_BASE 模式下的进程模型
①:Manager 进程:在 SWOOLE_BASE 模式下通过 Manager 进程来管理 Worker 进程,在此模式下如果 worker_num 设置为 1 的时候并且没有使用 Task 和 MaxRequest 特性时,底层将直接创建一个单独的 Worker 进程,不创建 Manager 进程。
②:Worker 进程:每个 Worker 进程同时承担了 SWOOLE_PROCESS 模式下 Reactor 线程和 Worker 进程两部分职责。
③:Task 进程:负责处理 Worker 进程投递的任务,执行完成后通过onFinish 事件将数据发送给 Worker 进程。
上面介绍了 Swoole 两种进程运行模型,我们来整理一下特性:
开发思维的转变
分析了 PHP-FPM 和 Swoole 两种运行模式,我们在 PHP-FPM 模式下大部分情况是在单独进程下执行代码,不需要我们关心资源回收,进程之间怎么通信等,网络通信 I/O 模型,服务端如何和客户端建立并保持连接等等,当我们转入到 Swoole 开发中的时候,我们必须从之前的舒适区走出来,了解更多操作系统的知识,比如:
- Reactor 模型是什么?
- 进程之间如何通信 (IPC)
- 请求的处理流程变化,参考上面的 Swoole 进程模型。
- ......
想要用上 Swoole 其实并不难,按照官方文档的 demo 很快就可以启动一个服务,然后把逻辑写到文档上告诉你的位置,但是要更好的适应 Swoole 的开发模式,就必须要清楚它的进程运行模型,了解后相信你对于 Swoole 会更加得心应手。