PHP-FPM 运行原理浅析
PHP-FPM 是什么?
了解 PHP-FPM 前我们需要先知道cgi
、php-cgi
、fast-cgi
CGI
为了解决不同的语言解释器 (如 php、python 解释器) 与 webserver 的通信,于是出现了 cgi 协议。只要你按照 cgi 协议去编写程序,就能实现语言解释器与 webwerver 的通信。如 php-cgi 程序。
来自百度百科
CGI是 Web 服务器运行时外部程序的规范,按 CGI 编写的程序可以扩展服务器功能。CGI 应用程序能与浏览器进行交互,还可通过数据库 API 与数据库服务器等外部数据源进行通信,从数据库服务器中获取数据。格式化为 HTML 文档后,发送给浏览器,也可以将从浏览器获得的数据放到数据库中。几乎所有服务器都支持 CGI,可用任何语言编写 CGI,包括流行的 C、C ++、VB 和 Delphi 等。CGI 分为标准 CGI 和间接 CGI 两种。标准 CGI 使用命令行参数或环境变量表示服务器的详细请求,服务器与浏览器通信采用标准输入输出方式。间接 CGI 又称缓冲 CGI,在 CGI 程序和 CGI 接口之间插入一个缓冲程序,缓冲程序与 CGI 接口间用标准输入输出进行通信。
FastCGI
有了 cgi 协议,解决了 php 解释器与 webserver 通信的问题,webserver 终于可以处理动态语言了。但是,webserver 每收到一个请求,都会去 fork 一个 cgi 进程,请求结束再 kill 掉这个进程。这样有 10000 个请求,就需要 fork、kill php-cgi 进程 10000 次。于是,出现了 cgi 的改良版本,fast-cgi。
fast-cgi 是 cgi 的升级版本,FastCGI 像是一个常驻 (long-live) 型的 CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去 fork 一 次。PHP 使用 PHP-FPM(FastCGI Process Manager),全称 PHP FastCGI 进程管理器进行管理。
来自百度百科
FastCGI 的工作原理
- Web Server 启动时载入 FastCGI 进程管理器 (IIS ISAPI 或 Apache Module)
- FastCGI 进程管理器自身初始化,启动多个 CGI 解释器进程 (可见多个 php-cgi) 并等待来自 Web Server 的连接。
- 当客户端请求到达 Web Server 时,FastCGI 进程管理器选择并连接到一个 CGI 解释器。Web server 将 CGI 环境变量和标准输入发送到 FastCGI 子进程 php-cgi。
- FastCGI 子进程完成处理后将标准输出和错误信息从同一连接返回 Web Server。当 FastCGI 子进程关闭连接时,请求便告处理完成。FastCGI 子进程接着等待并处理来自 FastCGI 进程管理器 (运行在 Web Server 中) 的下一个连接。 在 CGI 模式中,php-cgi 在此便退出了。
在上述情况中,你可以想象 CGI 通常有多慢。每一个 Web 请求 PHP 都必须重新解析 php.ini、重新载入全部扩展并重初始化全部数据结构。使用 FastCGI,所有这些都只在进程启>动时发生一次。一个额外的 好处是,持续数据库连接 (Persistent database connection) 可以工作。
PHP-CGI
PHP-CGI 是早期 php 官方出品的 FastCGI 管理器,也是用来解释 PHP 脚本的
PHP-FPM 是什么
据说是修改了 php.ini 配置文件后,没办法平滑重启,所以就诞生了 php-fpm
PHP-FPM(FastCGI Process Manager:FastCGI 进程管理器) 是一个实现了 Fastcgi 的程序,并且提供进程管理的功能。进程包括 master 进程和 worker 进程。master 进程只有一个,负责监听端口,接受来自 web server 的请求。worker 进程一般会有多个,每个进程中会嵌入一个 PHP 解析器,进程 PHP 代码的处理。
但是鉴于每次都会去读取php脚本,在进行解析,效率上也有一定的问题,所以php7.4引入了 预加载 ,使得服务器启动的时候,将某些文件永久读取到内存中,之后的请求即可直接从这内存中读取。利用这个功能,能够将框架,或者是类库预加载到内存中,以进一步提高性能,还能将php写的函数,当成内部函数使用(因为已经永久加载到内存,整个服务器共享)。不过这样也有一个问题,就是当这部分加载到服务器之后,文件有所更新就得重新启动服务器。
PHP-FPM(FastCGI Process Manager:FastCGI 进程管理器) 是一个 PHPFastCGI 管理器,对于 PHP 5.3.3 之前的 php 来说,是一个补丁包 [1] ,旨在将 FastCGI 进程管理整合进 PHP 包中。如果你使用的是 PHP5.3.3 之前的 PHP 的话,就必须将它 patch 到你的 PHP 源代码中,在编译安装 PHP 后才可以使用。
来自百度百科
相对 Spawn-FCGI,PHP-FPM 在 CPU 和内存方面的控制都更胜一筹,而且前者很容易崩溃,必须用 crontab 进行监控,而 PHP-FPM 则没有这种烦恼。
再来看 Nginx 与 Php-fpm 结合
我们可以看到 NGINX 的虚拟主机配置文件
server { listen 80; server_name www.example.com; #就是网站地址 root /usr/local/etc/nginx/www/huxintong_admin; # 准备存放代码工程的路径 #路由到网站根目录www.example.com时候的处理 location / { index index.php; #跳转到www.example.com/index.php } #当请求网站下php文件的时候,反向代理到php-fpm location ~ .php$ { fastcgi_pass 127.0.0.1:9000;#表示nginx通过fastcgi协议将用户请求的资源发给127.0.0.1:9000进行解析,这里的nginx和php脚本解析服务器是在同一台机器上,所以127.0.0.1:9000表示的就是本地的php脚本解析服务器。 include fastcgi_params;#加载fastcgi参数,可以理解为nginx会通过fastcgi协议处理本次请求 } }
当我们访问www.example.com
的时候,处理流程是这样的:
总结
当Web Server
收到 index.php
这个请求后,会启动对应的 CGI 程序,这里就是 PHP 的解析器。接下来 PHP 解析器会解析php.ini
文件,初始化执行环境,然后处理请求,再以规定 CGI 规定的格式返回处理后的结果,退出进程,Web server 再把结果返回给浏览器。这就是一个完整的动态 PHP Web 访问流程,接下来再引出这些概念,就好理解多了,
CGI
:是 Web Server 与 Web Application 之间数据交换的一种协议。
FastCGI
:同 CGI,是一种通信协议,但比 CGI 在效率上做了一些优化。同样,SCGI 协议与 FastCGI 类似。
PHP-CGI
:是 PHP(Web Application)对 Web Server 提供的 CGI
协议的接口程序。
PHP-FPM
:是 PHP(Web Application)对 Web Server 提供的 FastCGI 协议的接口程序,额外还提供了相对智能一些任务管理。