FastCGI与PHP-FPM
要想弄清FastCGI和PHP-FPM,就需要先弄清一些基本的概念: CGI
FastCGI
PHP-FPM
PHP-CGI
。
CGI
通用网关接口,描述的服务器和请求处理程序之间的数据传输的一种标准。
这可以简单的理解为CGI
就是保证web server
传过来的数据是标准的,能够方便的请求处理程序的编写。
在这一层面之上,web server
只是请求内容的分发者。比如,如果请求index.html
,那么web server
会去文件系统中查找这个文件,然后发送到浏览器,那么这里分发的就是静态资源。如果这个时候请求的不是index.html
而是index.php
的话,根据web server
(比如nginx
)的配置文件,server
判断出此次请求的不是静态文件,而是一个PHP的程序,需要去找PHP解析器来处理,那么server会简单处理这个请求后交给PHP解析器。Nginx
会将请求的URL
、GET/POST数据
、HTTP Header
等协议规定好的数据传递到处理请求的CGI程序
中。
让我们在具体一点的分析。当server
收到index.php
这个请求后,server
会启动对应的CGI程序,本文中指的就是PHP的解析器。接下来PHP解析器会解析配置文件php.ini
,初始化运行环境,然后处理请求,最后按照CGI规定的数据格式返回处理结果,同时退出当前的CGI程序的进程。server
将CGI程序的结果返回到浏览器中。
说了这么多,重点就是CGI是一个相互通信的协议,是一种双方约定好的标准。
FastCGI
在上面的CGI
中,我们可以看到,当请求来临的时候CGI会初始化运行环境,然后处理请求
,标准的CGI会对每一个请求都执行这些操作,所以每次的处理时间会很长,毕竟频繁的启动进程会消耗大量的资源。
FastCGI
就是为了解决这种缺陷而出现的。FastCGI
是CGI
的增强版,为了减少web server
与CGI
程序之间的互动开销,从而使server能够同时处理更多的请求。
那么FastCGI
是如何做到的呢?首先,FastCGI
会先启动一个master
进程,解析配置文件,初始化运行环境,然后在启动多个worker
进程。当请求来临时,server
将请求传递到master
,master
将请求传递给一个已经启动了的worker
,然后就可以接收下一个请求;worker
处理完请求便可以直接将处理的标准输出和错误信息返回到server
。这样就避免了每次处理请求时都需要做的forkCGI进程
的工作。当请求太多,worker
不够用的时候,master
可以根据配置文件预先启动多个worker
等着;当worker
空闲太多时,也会停掉一些。大多数的FastCGI
实现都会维护一个进程池(swoole作为HttpServer时,就是类似这样的工作方式)。
到现在我们了解了CGI
和FastCGI
:
由于CGI处理每一个请求都需要fork新的进程,效率底下,就出现了CGI的增强版FastCGI,FastCGI维护一个自己的进程池来避免fork新进程的开销,从而大大的提高了性能。
PHP-CGI、PHP-FPM
PHP-CGI
是PHP自带的FastCGI管理器
,然而他却存在着比较严重的问题:
PHP-CGI
变更php.ini
配置后需重启PHP-CGI
才能让新的php-ini
生效,不可以平滑重启.- 直接杀死
PHP-CGI
进程,PHP就不能运行了。(PHP-FPM
就没有这个问题,守护进程会平滑从新生成新的子进程。)
针对上面的两个问题,PHP-FPM
便应运而生。PHP-FPM
提供了更好的PHP进程管理方式,可以有效控制内存和进程、可以平滑重载PHP配置。由于PHP-FPM
的优异表现,PHP官方在PHP5.3.3中集成PHP-FPM
,使得PHP-FPM
越来越受欢迎。