在搭建LAMP/LNMP服务器时,会经常遇到PHP-FPM、FastCGI和CGI这几个概念。如果对它们一知半解,很难搭建出高性能的服务器。接下来我们就以图形方式,解释这些概念之间的关系。
一、客户端请求
在整个网站架构中,WebServer(如Apache/Nginx)只是内容的分发者。举个栗子,如果客户端请求的是index.html,那么WebServer会去文件系统中找到这个文件,发送给浏览器,这里分发的是静态数据。如下图:
如果请求的是index.php,根据配置文件,WebServer知道这个不是静态文件,需要去找PHP解析器来处理。那么他会把这个请求简单处理,然后交给PHP解析器。
当WebServer收到index.php这个请求后,会启动对应的CGI程序,这里就是PHP的解析器(PHP-CGI)。接下来PHP解析器会解析php.ini文件,初始化执行环境,然后处理请求,再以CGI规定的格式返回处理后的结果,退出进程,Webserver再把结果返回给浏览器。这就是一个完整的动态PHPWeb访问流程,接下来再引出这些概念,就好理解多了。
二、概念初识
1.CGI:是WebServer与WebApplication之间数据交换的一种协议。
2.FastCGI:同CGI,是一种通信协议,但比CGI在效率上做了一些优化。同样,SCGI协议与FastCGI类似。
3.PHP-CGI:是PHP(WebApplication)对WebServer提供的CGI协议的接口程序。
4.PHP-FPM:是PHP(WebApplication)对WebServer提供的FastCGI协议的接口程序,额外还提供了相对智能的一些任务管理。
补充:可以说php-fpm不仅仅是用来在webserver和php之间通信的fastCGI接口程序。同样还是PHP的进程池管理工具。
6.WebApplication:一般指PHP、Java、Asp.net等应用程序。
三、CGI协议
1.概念
CGI全称是“公共网关接口”(CommonGatewayInterface),HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上。
CGI可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量。如php、perl、tcl等。
2.工作原理
CGI就是专门用来和web服务器打交道的。web服务器收到用户请求,就会把请求提交给CGI程序(如PHP-CGI),CGI程序根据请求提交的参数作应处理(解析PHP),然后输出标准的html语句,返回给web服务器,WEB服务器再返回给客户端,这就是普通CGI的工作原理。
3.缺点
四、FastCGI协议
FastCGI是CGI的升级版,也是一种通信协议,它是用来提高CGI程序性能的。
2.特点
FastCGI的特点是会在一个进程中依次完成多个请求,以达到提高效率的目的,大多数FastCGI实现都会维护一个进程池。
3.工作原理
1)WebServer启动时载入FastCGI进程管理器(IISISAPI或ApacheModule)
2)FastCGI进程管理器自身初始化,启动多个CGI解释器进程(多个PHP-CGI)并等待来自WebServer的连接。
3)当客户端请求到达WebServer时,FastCGI进程管理器选择并连接到一个CGI解释器。WebServer将CGI环境变量和标准输入发送到FastCGI子进程PHP-CGI。
4)FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回WebServer。当FastCGI子进程关闭连接时,请求便处理完成。FastCGI子进程接着等待并处理来自进程管理器(运行在WebServer中)的下一个连接。在CGI模式中,PHP-CGI在此便退出了。
FASTCGI与CGI的区别:
在上述情况中,你可以想象CGI通常有多慢。每一个Web请求,PHP都必须重新解析php.ini、重新载入全部扩展并重新初始化全部数据结构。
使用FastCGI,所有这些都只在进程启动时发生一次。一个额外的好处是,持续数据库连接(Persistentdatabaseconnection)可以工作。
4.FastCGI对进程的管理
FastCGI会先启动一个master,解析配置文件,初始化执行环境,然后再启动多个worker。当请求过来时,master会传递给一个worker,然后立即可以接受下一个请求。这样就避免了重复的劳动,效率自然是高。而且当worker不够用时,master可以根据配置预先启动几个worker等着;当然空闲worker太多时,也会停掉一些,这样就提高了性能,也节约了资源。
五、PHP-CGI(CGI协议的接口程序)
PHP-CGI实现了CGI协议,它是PHP的解释器。
PHP-CGI只是个CGI程序,他自己本身只能解析请求,返回结果,不会进程管理(皇上,臣妾真的做不到啊!)
PHP-CGI的不足:
1)PHP-CGI变更php.ini配置后需重启PHP-CGI才能让新的php-ini生效,不可以平滑重启。直接杀死PHP-CGI进程,PHP就不能运行了。(PHP-FPM和Spawn-FCGI就没有这个问题,守护进程会平滑重启生成新的子进程。)
2)不支持动态worker调度,只能一开始指定要起几个worker。
六、PHP-FPM(FASTCGI协议的接口程序)
PHP-FPM是针对于PHP的,它实现了FASTCGI协议。同时,它负责管理一个进程池,处理来自Web服务器的请求。目前,PHP-FPM是内置于PHP的。
七、PHP-FPM与PHP-CGI的区别
最初PHP-FPM是需要调用PHP-CGI来解释PHP代码的,PHP-FPM只起到进程管理的作用,但是因为PHP-FPM这个民间第三方写的工具实在比PHP-CGI好太多了,PHP官方在PHP5.4时就把它集成到了PHP官方发布的包中,并且PHP-FPM不需要再依赖PHP-CGI,直接把PHP解释器的功能集成进PHP-FPM了。
注意:win不支持PHP-FPM,因为PHP-FPM是使用Linux的fork()来做的,所以win下面基本上还是使用PHP-CGI,当然有人用“Cygwin”这个软件可以在win下模拟Linux的fork(),但如果你是本地开发环境就没必要这么做了,用win10做开发的我建议你们考虑一下wsl。
六、比喻
在网上看到有人做了一个很形象的比喻,虽然不全面,但是非常适合新手入门,去理解CGI、FastCGI、PHP-CGI与PHP-FPM之间的关系:
你(PHP)去和爱斯基摩人(web服务器,如Apache、Nginx)谈生意
你说中文(PHP代码),他说爱斯基摩语(C代码),互相听不懂,怎么办?那就都把各自说的话转换成英语(FastCGI协议)吧。
怎么转换呢?你就要使用一个翻译机(PHP-FPM)(当然对方也有一个翻译机,那个是他自带的)。我们这个翻译机是最新型的,老式的那个(PHP-CGI)被淘汰了。不过它(PHP-FPM)只有年轻人(Linux系统)会用,老头子们(Windows系统)不会摆弄它,只好继续用老式的那个。
七、总结
最后,我们来总结一下,这些技术经过不断的升级,可以解决什么问题(不然也不会升级嘛)。
所以,如果要搭建一个高性能的PHPWEB服务器,目前最佳的方式是Apache/Nginx+FastCGI+PHP-FPM(+PHP-CGI)方式了,不要再使用Module加载或者CGI方式啦。