php-fpm 与workerman 运行模型
php-fpm 的worker 是否常驻内存
为什么很多人认为fpm不常驻
fpm的请求生命周期是什么
Workerman 为什么叫常驻内存框架
Workerman 的事件循环是什么
两者如何管理数据库连接
两者分别适合什么场景
重要
PHP-FPM: Worker 进程通常常驻 请求状态通常不常驻
Workerman: Worker 进程常驻 应用对象和状态可以跨请求保留
fpm
php-fpm的启动过程
启动 PHP-FPM
↓
创建 master 主进程
↓
读取配置
↓
创建多个 Worker 子进程
↓
Worker 等待 FastCGI 请求
PHP-FPM master
├── 创建和管理 Worker 1
├── 创建和管理 Worker 2
└── 创建和管理 Worker 3
请求路径:
Nginx
↓ FastCGI
PHP-FPM 监听端口或 Unix Socket
↓
某个空闲 Worker
↓
执行 PHP 脚本FastCGI 是什么
- FastCGI 是 Web 服务器和后端应用程序之间的一种通信协议。
在常见的 PHP-FPM 架构中:
浏览器
↓ HTTP
Nginx
↓ FastCGI
PHP-FPM Worker
↓
执行 PHP 脚本
↓ FastCGI
Nginx
↓ HTTP
浏览器Nginx 本身通常不负责执行 PHP 代码。当请求访问 PHP 文件时,Nginx 会通过 FastCGI 协议,把请求信息发送给 PHP-FPM。
这些信息通常包括:
要执行的 PHP 文件
请求方法
GET 参数
POST 数据
请求头
客户端地址例如:
SCRIPT_FILENAME=/var/www/index.php
REQUEST_METHOD=GET
QUERY_STRING=id=100
HTTP_HOST=example.com
REMOTE_ADDR=192.168.1.10PHP-FPM 的某个空闲 Worker 接收到 FastCGI 请求后,会执行对应的 PHP 脚本,并把执行结果通过 FastCGI 返回给 Nginx。
需要注意:
master:管理 Worker 进程
Worker:接收 FastCGI 请求并执行 PHPNginx 的请求并不是先交给 master 执行业务。master 主要负责创建、监控、回收和重启 Worker。
PHP-FPM 可以理解为 PHP 对 FastCGI 协议的一种进程管理实现,其全称是:
PHP FastCGI Process ManagerCGI 和 FastCGI 的区别
传统 CGI 通常是每次请求都创建一个新进程:
请求到达
→ 创建 PHP 进程
→ 执行 PHP
→ 返回响应
→ 进程退出FastCGI 则会提前维护一批可重复使用的 Worker 进程:
提前创建 Worker
→ 请求到达
→ 空闲 Worker 处理请求
→ 请求结束
→ Worker 继续等待下一个请求因此,FastCGI 的重点是:
重要
进程可以被多个请求重复使用 但每个请求仍然拥有相对独立的请求生命周期
PHP-FPM master 和 Worker 的职责
master:
- 创建 Worker
- 回收 Worker
- 监控 Worker
- 重启异常 Worker
- 管理 Worker 数量
Worker:
- 接收请求
- 执行 PHP 脚本
- 返回响应
- 清理请求状态
- 继续等待下一个请求
php-fpm二个生命周期
Worker进程生命周期
Worker 启动
→ 处理请求 1
→ 处理请求 2
→ 处理请求 3
→ 被回收或重启单次请求生命周期
请求开始
→ 加载应用
→ 创建变量和对象
→ 执行业务
→ 返回响应
→ 清理请求数据FPM 常驻的是 Worker 进程,不常驻的是普通请求状态。
PHP-FPM 的进程管理模式
提示
- static 固定 Worker 数量
- dynamic 根据空闲数量增减
- ondemand 请求来了才创建,空闲后回收
PHP-FPM 的数据库连接
普通连接模型
请求开始
→ 第一次访问数据库
→ 创建数据库连接
→ 执行 SQL
→ 请求结束
→ 连接通常释放持久连接模型
某个 FPM Worker
└── 维护自己的持久连接提示
不同 Worker 之间不能共享普通连接对象
一个请求是否创建连接,取决于业务是否访问数据库
持久连接也只属于当前 Worker
PHP-FPM 的 worker 是操作系统进程,不是线程。
Workerman
Workerman的启动过程
执行 php start.php start
↓
创建 master(主进程)
↓
创建多个 Worker 进程
↓
执行 onWorkerStart
↓
进入事件循环
↓
持续监听请求或连接Workerman 为什么是常驻内存
因为一个 Worker 启动后:
应用代码加载一次
对象可以继续存在
数据库连接可以复用
定时器可以持续运行
全局状态可能跨请求保留
请求结束后不会自动清理整个应用环境Workerman的事件循环
- 核心模型
等待网络事件
↓
收到新连接
↓
收到消息
↓
执行回调
↓
返回事件循环- 例如:
onWorkerStart:Worker 启动时执行
onConnect:新连接建立时执行
onMessage:收到消息时执行
onClose:连接关闭时执行Workerman 的数据库连接
Worker 启动
→ 创建数据库连接或连接池
→ 多个请求复用
→ 连接断开后重连
→ Worker 关闭时释放- 需要提醒
每个 Worker 有自己的数据库连接
连接不能跨进程直接共享
长连接可能因数据库超时失效
必须考虑心跳、重连和连接池Workerman 的常驻内存风险
状态污染
静态变量残留
内存泄漏
未清理的请求数据
事务没有回滚
数据库连接失效
阻塞事件循环
修改代码后需要 reload 或 restart提示
Workerman 的 Worker 是独立进程,不是线程。
PHP-FPM 与 Workerman 综合对比
| 对比项 | PHP-FPM | Workerman |
|---|---|---|
| 运行方式 | 通过 FastCGI 接收请求的 PHP 进程管理器 | 基于 PHP CLI 的常驻应用服务器 |
| Worker 是否常驻 | 通常常驻 | 常驻 |
| 请求状态 | 通常请求结束后清理 | 可跨请求保留 |
| 应用初始化 | 通常每个请求走入口 | 每个 Worker 启动一次 |
| 普通数据库连接 | 常按请求创建 | 常由 Worker 长期持有 |
| 长连接 | 不擅长 | 擅长 |
| WebSocket | 不适合大量直接承载 | 非常适合 |
| 状态污染风险 | 较低 | 较高 |
| 阻塞影响 | 占住一个 Worker | 阻塞当前事件循环 |
| 代码更新 | 通常下次请求重新执行 | 一般需要 reload |
结论
重要
FPM: 进程常驻,请求状态通常不常驻。
Workerman: 进程和应用环境都可以常驻。
两者不是谁更高级, 而是解决的问题不同。
PHP-FPM 与 Workerman 适用场景
| 业务场景 | PHP-FPM | Workerman | 说明 |
|---|---|---|---|
| 普通网站 | ✅ 适合 | ⚠️ 可以使用 | 普通页面请求通常使用 PHP-FPM 即可 |
| 管理后台 | ✅ 适合 | ⚠️ 可以使用 | 以短请求和 CRUD 操作为主 |
| 电商业务 | ✅ 适合 | ⚠️ 部分场景适合 | 普通商城业务适合 PHP-FPM,实时通知等功能可使用 Workerman |
| CMS (管理后台的网站) | ✅ 适合 | ❌ 通常没必要 | WordPress、Drupal 等通常运行在 PHP-FPM 中 |
| REST API | ✅ 适合 | ✅ 适合 | 短请求 API 适合 PHP-FPM,高并发常驻服务可考虑 Workerman |
| 短请求业务 | ✅ 非常适合 | ⚠️ 可以使用 | PHP-FPM 的请求隔离模型更简单 |
| WebSocket | ❌ 不适合直接承载 | ✅ 非常适合 | WebSocket 需要维护长连接 |
| 即时通信 | ❌ 不适合 | ✅ 非常适合 | 需要持续维护用户连接和实时收发消息 |
| 实时推送 | ❌ 不适合 | ✅ 非常适合 | Workerman 可以主动向客户端推送数据 |
| TCP 服务 | ❌ 不适合 | ✅ 非常适合 | Workerman 可以直接监听和处理 TCP 连接 |
| 游戏服务器 | ❌ 不适合 | ✅ 适合 | 适合实时通信、房间状态和长连接场景 |
| 长连接网关 | ❌ 不适合 | ✅ 非常适合 | Workerman 的事件循环适合管理大量长连接 |
简单选择原则
| 需求特点 | 推荐方案 |
|---|---|
| 请求到来后执行,响应完成后结束 | PHP-FPM |
| 以网页、后台、CMS、普通 API 为主 | PHP-FPM |
| 需要请求之间保持连接或应用状态 | Workerman |
| 需要 WebSocket、TCP、实时通信 | Workerman |
| 需要维护大量长期在线连接 | Workerman |
| 普通业务与实时业务同时存在 | PHP-FPM + Workerman |
版权所有
版权归属:念宇
