答案是:不一定。这取决于你使用的 PHP 运行模式(SAPI)。

  • 在传统的 PHP-FPM (Nginx/Apache) 模式下是的,通常是两个独立的进程。
  • 在 Hyperf/Swoole (常驻内存) 模式下不是,通常是同一个进程内的两个协程 (Coroutines) 或线程。

如果把服务器比作一家餐厅

  • PHP-FPM:是快餐店模式
    • 机制:每个顾客(请求)来了,经理就叫一个空闲的厨师(Worker 进程)专门服务他。服务完,厨师休息或下班。
    • 结果:两个顾客 = 两个厨师(两个进程)。他们互不干扰,隔离性极好,但切换成本高。
  • Hyperf/Swoole:是高端居酒屋/寿司吧台模式
    • 机制:只有一个或几个大厨(Worker 进程)坐在吧台后。
    • 结果:两个顾客(请求)来了,大厨左手给 A 捏寿司,右手给 B 倒酒(协程切换)。
    • 本质:两个顾客由 同一个厨师(进程) 通过 快速切换注意力(协程) 来服务。
    • 核心逻辑别以为多个人吃饭就需要多个厨房。高手可以用一只手同时伺候多桌客人,只要他切换得够快。

一、传统模式:PHP-FPM (Multi-Process)

1. 机制:Pre-fork 模型
  • 启动时:Nginx 启动一组 PHP-FPM Worker 进程(如 5 个)。
  • 请求到来
    • 浏览器 A 请求 -> Nginx 转发给 FPM -> FPM 管理器分配 Worker Process 1
    • 浏览器 B 请求 -> Nginx 转发给 FPM -> FPM 管理器分配 Worker Process 2(如果 Process 1 忙)。
  • 执行
    • Process 1 加载 PHP 代码,初始化环境,执行业务逻辑,返回结果,然后重置状态等待下一个请求。
    • Process 2 同理。
  • 结论是两个完全独立的操作系统进程。
    • 内存隔离:Process 1 的变量不会影响 Process 2。
    • PID 不同:在服务器上 ps aux | grep php-fpm 能看到两个不同的 PID。
2. 特点
  • 优点:稳定性高。一个进程崩溃(Segfault)不影响其他进程。
  • 缺点:资源消耗大。每个进程都要加载完整的框架、配置文件、类定义。并发高时,进程上下文切换开销大。

二、现代模式:Hyperf/Swoole (Multi-Coroutine / Multi-Thread)

1. 机制:Event Loop + Coroutine
  • 启动时:Hyper 启动 4 个 Worker 进程(假设配置 worker_num=4)。
  • 请求到来
    • 浏览器 A 请求 -> Swoole Event Loop 接收 -> 在 Worker Process 1 中创建 Coroutine A
    • 浏览器 B 请求 -> Swoole Event Loop 接收 -> 在 Worker Process 1 中创建 Coroutine B(或者分配到 Worker Process 2,取决于负载均衡)。
  • 执行
    • Coroutine A 执行到 IO 操作(查数据库),挂起 (Yield),让出 CPU。
    • Coroutine B 获得 CPU 时间片,开始执行。
    • 数据库返回结果,Coroutine A 恢复 (Resume),继续执行。
  • 结论通常是在同一个进程内,由两个协程并发处理。
    • 内存共享:Coroutine A 和 B 共享同一个进程的内存空间(全局变量、静态属性)。
    • PID 相同:在服务器上 ps aux | grep hyperf 可能只看到一个 Worker 进程在处理这两个请求。
2. 特点
  • 优点:极高并发。无需创建/销毁进程,内存复用,上下文切换极快(用户态切换)。
  • 缺点:开发门槛高。必须注意 协程安全,避免在协程间共享可变状态导致数据污染。

三、特殊情况:多线程 (ZTS / Apache Worker MPM)

  • Apache Worker MPMPHP ZTS (Zend Thread Safety) 模式:
    • 一个进程内包含多个 线程 (Threads)
    • 两个请求可能由 同一个进程内的两个不同线程 处理。
    • 结论:是一个进程,两个线程。
    • 现状:这种模式在现代 PHP Web 开发中已较少见,主流是 FPM(多进程)或 Swoole/OpenSwoole(多进程+协程)。

四、认知牢笼:常见误区

1. 误区:“浏览器开了两个窗口,服务器就必须开两个进程。”
  • 真相:服务器如何处理请求,取决于 服务器架构,而非客户端行为。
  • 对策:理解服务器的并发模型。FPM 是“一人一事”,Swoole 是“一人多事”。
2. 误区:“Swoole 下,两个请求绝对在同一个进程。”
  • 真相:不一定。
    • 如果配置了 worker_num=4,且有 4 个空闲 Worker,Nginx/Swoole 可能会将请求轮询分发到不同的 Worker 进程。
    • 但如果只有 1 个 Worker,或者该 Worker 很忙,它们可能在同一进程。
    • 关键:即使在不同进程,它们也是 协程 而非传统意义上的“进程阻塞”。
3. 误区:“进程比协程安全,所以 FPM 更好。”
  • 真相
    • FPM:进程隔离带来安全性,但牺牲了性能。
    • Swoole:协程共享内存带来高性能,但要求开发者具备 线程/协程安全意识(如无状态设计、Context 管理)。
    • 对策:根据项目规模选择。小项目 FPM 足够;高并发微服务选 Swoole/Hyperf。
4. 误区:“我可以利用‘两个进程’来通信。”
  • FPM:进程间通信 (IPC) 很麻烦(Redis, Socket, Shared Memory)。
  • Swoole:同进程内协程通信很简单(Channel, Context);跨进程通信需用 Table, Redis, MQ。
  • 对策:不要依赖进程ID来做业务逻辑。使用分布式 ID 或会话存储。

🚀 总结:原子化“浏览器窗口 vs. PHP 进程”全景图

维度 PHP-FPM (传统) Hyperf/Swoole (现代)
并发模型 多进程 (Multi-Process) 多进程 + 多协程 (Multi-Coroutine)
两个请求 通常对应两个独立进程 通常对应同一进程内的两个协程
内存隔离 完全隔离 (进程级) 部分共享 (进程内协程共享内存)
资源开销 (每次加载框架) (内存常驻,复用对象)
安全性 (崩溃不影响其他) (需防止协程间数据污染)
PHP 隐喻 Multiple Chefs vs. One Chef with Two Hands
公式 Requests = Processes (FPM); Requests = Coroutines (Swoole)

终极心法

浏览器窗口的数量,不等于服务器进程的数量。
FPM 用空间换隔离,Swoole 用复杂度换性能。
理解你的战场,才能选择正确的武器。
于进程中见隔离,于协程见并发;以模型为尺,解混淆之牛,于架构选型中,求适配之真。

行动指令

  1. 检查环境:确认你的项目是跑在 FPM 还是 Hyperf/Swoole 上。
  2. 观察进程
    • FPM: ps aux | grep php-fpm,发起两个请求,看是否新增或占用不同 PID。
    • Hyperf: ps aux | grep hyperf,发起两个请求,观察 Worker 进程的 CPU 变化,PID 通常不变。
  3. 思维升级:记住,在 Hyperf 中,你要担心的不是“进程冲突”,而是“协程上下文污染”。确保你的代码是无状态的,或者正确使用 Context
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐