PHP-FPM vs Swoole

前几天看见有几篇讲 swoole 的文章,今天我也来凑个热闹。水平有限,细节理解可能不到位,欢迎大家帮我补充、纠正。

PHP-FPM

早期版本的 PHP 并没有内置的 WEB 服务器,而是提供了 SAPI(Server API)给第三方做对接。现在非常流行的 php-fpm 就是通过 FastCGI 协议来处理 PHP 与第三方 WEB 服务器之间的通信。比如 Nginx + php-fpm 的组合,这种方式运行的 fpm 是 Master/Worker 模式,启动一个 Master 进程监听来自 Nginx 的请求,再 fork 多个 Worker 进程处理请求。每个 Worker 进程只能处理一个请求,单一进程的生命周期大体如下:

  1. 初始化模块。
  2. 初始化请求。此处请求是请求 PHP 执行代码的意思,并非 HTTP 的请求。
  3. 执行 PHP 脚本。
  4. 结束请求。
  5. 关闭模块。

对细节感兴趣的可以点这里看图

多进程模型是依赖进程数来解决并发问题,一个进程只能处理一个连接,当启动大量进程,进程调度消耗可能占 CPU 的百分之几十甚至 100%,比如 C10K 问题,多进程模型就力不从心了。

Swoole

Swoole 采用的也是 Master/Worker 模式,不同的是 Master 进程有多个 Reactor 线程,Master 只是一个事件发生器,负责监听 Socket 句柄的事件变化。Worker 以多进程的方式运行,接收来自 Reactor 线程的请求,并执行回调函数(PHP 编写的)。启动 Master 进程的流程大致是:

  1. 初始化模块。
  2. 初始化请求。因为 swoole 需要通过 cli 的方式运行,所以初始化请求时,不会初始化 PHP 的全局变量,如 $_SERVER, $_POST, $_GET 等。
  3. 执行 PHP 脚本。包括词法、语法分析,变量、函数、类的初始化等,Master 进入监听状态,并不会结束进程。

Swoole 加速的原理

  • 由 Reactor(epoll 的 IO 复用方式)负责监听 Socket 句柄的事件变化,解决高并发问题。
  • 通过内存常驻的方式节省 PHP 代码初始化的时间,在使用笨重的框架时,用 swoole 加速效果是非常明显的。

对比不同

PHP-FPM

  • Master 主进程 / Worker 多进程模式。
  • 启动 Master,通过 FastCGI 协议监听来自 Nginx 传输的请求。
  • 每个 Worker 进程只对应一个连接,用于执行完整的 PHP 代码。
  • PHP 代码执行完毕,占用的内存会全部销毁,下一次请求需要重新再进行初始化等各种繁琐的操作。
  • 只用于 HTTP Server。

Swoole

  • Master 主进程(由多个 Reactor线程组成)/ Worker 多进程(或多线程)模式
  • 启动 Master,初始化 PHP 代码,由 Reactor 监听 Socket 句柄的事件变化。
  • Reactor 主线程负责子多线程的均衡问题,Manager 进程管理 Worker 多进程,包括 TaskWorker 的进程。
  • 每个 Worker 接受来自 Reactor 的请求,只需要执行回调函数部分的 PHP 代码。
  • 只在 Master 启动时执行一遍 PHP 初始化代码,Master 进入监听状态,并不会结束进程。
  • 不仅可以用于 HTTP Server,还可以建立 TCP 连接、WebSocket 连接。

以上主要针对核心运行机制作对比,列举的不同,暂时就想到这几点了,如果有漏掉的重点,欢迎大家帮我补充啦~

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 5年前 自动加精
讨论数量: 19

多个 Reactor 线程,每个Reactor线程都调用一个epoll()函数么?
那master中默认开启多少个Reactor线程啊

6年前 评论

@Max epoll 是一种思想并不只是 epoll 这一个函数,每个 reactor 都是 I/O 复用的。无论 reactor_num 还是 worker_num 都可以设置的,reactor_num 不能大于 worker_num,还有其实 swoole 的 worker 还可以是多线程的。

6年前 评论

@chenos 哦哦,我一直以为多线程和异步非阻塞是对立的。
多线程存在一些竞态问题并发效率并不高。
之前我以为swoole和nginx一样直接使用epoll这个系统调用实现i/o复用,?

6年前 评论

@Max Nginx 还是 Swoole 都是 epoll 方式的 IO 复用,只不过 Nginx 是多进程 Reactor,Swoole 是多线程 Reactor + 多进程 Worker 的。golang 是单线程Reactor + 多线程协程,现在 swoole 也有协程了。

6年前 评论

@chenos 好,我去了解了解 Reactor

6年前 评论

@Max nginx 只负责 reactor,worker 部分由第三方负责,比如 nginx + php-fpm,php-fpm 在这里其实就是 worker,worker 还可以是处理其他语言的进程。

6年前 评论

@chenos
稍微了解了一下 Reactor. 其是基于epoll实现一种事件处理模型(或者说是一种设计模式,以oo思想来处理事件.)
换句话说.其实Reactor才是一种思想?一种规范?一个模型? epoll系列系统调用是才是这种思想的实现工具/技术

不过我还是不是很明白多线程Reactor的好处(如果每个线程占用一个cpu核心倒是可以理解),再去学习学习

6年前 评论

@Max 不仅仅 epoll 还有 select/poll/kqueue 这些都是 IO 复用的各种方式(也可以说是机制,不是什么模式),有一系列系统调用函数。Reactor 也可以叫 EventLoop,Event 是核心,Loop 是机制,Loop 可以用 select/poll/epoll/kqueue 中的任意方式。无论 epoll 还是 reactor 都是技术也是思想,解决不同的问题。照这个思路了解,然后你再来看看多线程有什么好处。

6年前 评论

@chenos

file

http://maxwei.me/posts/python-asyncio.html

event loop我自认为还是很了解的?.reactor和proactor才听说,不过大概也了解了.

  • 刚刚查了一下线程处理一些短链接响应速度快,并发能力高.还是很ok的. 我抽空去看看swoole的master好了
6年前 评论

协程开销更小,一个请求启动一个协程。

6年前 评论

看了php-fpm和swoole在M-W模式上的区别,但还是不理解为什么swoole性能上有优势?进程管理上应该是没有本质区别的,swoole也是一个请求占用一个worker进程。那么优势就是在swoole的worker可以 “通过内存常驻的方式节省 PHP 代码初始化的时间”?这个 “PHP代码初始化” 具体是指哪一些呢?比如PHP扩展吗?这些fpm worker也已经做了吧。请教~

5年前 评论

少年你没理解到php-fpm!!!

5年前 评论
medz

高性能多线程

高性能异步

高性能常驻

高性能复用资源
如果您真的很喜欢 Swoole 建议你先阅读官方文档,理解「概述」所说的事情!

5年前 评论
medz

韩天峰韩大佬早就说过,swoole 就是解决 PHP 没有覆盖到的地方的需求(参考惠新辰&韩天峰微博),您这种给我的感觉有点类似去年「区块链」的感觉,一句「swoole 啥都能做,swoole 啥都好」,当然我不是贬低 swoole,我很喜欢 swoole,我用它来做它应该出现的场景,例如需要常驻的任务处理器。

5年前 评论

@岁月神偷 请把您觉得理解到为的 php-fpm 发表下,OK?键盘侠。

5年前 评论

@medz 多谢指点,能帮我指正下文章具体错在哪里吗?或者有哪些不足的,我好具体去研究学习一下。

另外你说的那些好像我也没说过吧?

5年前 评论
medz

@chenos 感谢回复,我简单说一不对的地方吧,其实也没有不对,只是不合适。php-fpm vs swoole 本身定位并不是相同的,这两个比较没有说服力。其次,swoole 跟多的是解决一些 php 覆盖不到的问题,例如协程、异步,还有就是协议通信这一块,其次就是 php-fpm 薄弱的地方,例如 Windows 环境,虽然 swoole 也正在改善 Windows 支持,但是依旧不好。与其说 swoole 来和 php-fpm 对比,不如说 swoole 是在拓展 php 的更多可行性。

5年前 评论
medz

@chenos 第一条回复内容我已经更改了,我刚刚阅读发现使用了不合适的文字,抱歉。

5年前 评论
medz

顺便说一下,用 swoole 和 php-fpm 做同样的事情,从单机测试参数来看 swoole 可能确实要好很多,但是如果真的实际运用到一个架构体系中 http 的表现能力不一定有 php-fpm 好,因为这不是 swoole 的强项。

5年前 评论
道法自然 4年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!