CGI、FastCGI、PHP-CGI与PHP-FPM的概念以及各个之间的关系
CGI、FastCGI、PHP-CGI与PHP-FPM的概念以及各个之间的关系
概要
在搭建 LAMP/LNMP 服务器时,会经常遇到 PHP-FPM、FastCGI和CGI 这几个概念。如果对它们一知半解,很难搭建出高性能的服务器。接下来我们就以图形方式,解释这些概念之间的关系。
一、客户端请求
在整个网站架构中,Web Server(如Apache/Nginx)只是内容的分发者。举个栗子,如果客户端请求的是 index.html,那么Web Server会去文件系统中找到这个文件,发送给浏览器,这里分发的是静态数据。如下图:
如果请求的是 index.php,根据配置文件,Web Server知道这个不是静态文件,需要去找 PHP 解析器来处理。那么他会把这个请求简单处理,然后交给PHP解析器。
当Web Server收到 index.php 这个请求后,会启动对应的 CGI 程序,这里就是PHP的解析器(PHP-CGI)。接下来PHP解析器会解析php.ini文件,初始化执行环境,然后处理请求,再以CGI规定的格式返回处理后的结果,退出进程,Web server再把结果返回给浏览器。这就是一个完整的动态PHP Web访问流程,接下来再引出这些概念,就好理解多了。
二、概念初识
1. CGI:是 Web Server 与 Web Application 之间数据交换的一种协议。
2. FastCGI:同 CGI,是一种通信协议,但比 CGI 在效率上做了一些优化。同样,SCGI 协议与 FastCGI 类似。
3. PHP-CGI:是 PHP (Web Application)对 Web Server 提供的 CGI 协议的接口程序。
4. PHP-FPM:是 PHP(Web Application)对 Web Server 提供的 FastCGI 协议的接口程序,额外还提供了相对智能的一些任务管理。
补充:可以说php-fpm不仅仅是用来在web server 和 php之间通信的fastCGI接口程序。同样还是 PHP 的进程池管理工具。
5. Web Server :一般指Apache、Nginx、IIS、Lighttpd、Tomcat等服务器,
6. Web Application :一般指PHP、Java、Asp.net 等应用程序。
三、CGI 协议
1. 概念
CGI全称是“公共网关接口”(Common Gateway Interface),HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上。
CGI可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量。如 php、perl、tcl等。
2. 工作原理
CGI就是专门用来和 web 服务器打交道的。web服务器收到用户请求,就会把请求提交给 CGI 程序(如PHP-CGI),CGI 程序根据请求提交的参数作应处理(解析PHP),然后输出标准的html语句,返回给web服务器,WEB服务器再返回给客户端,这就是普通 CGI 的工作原理。
3. 缺点
每一次web请求都会有启动和退出过程,也就是每次都要花费时间去fork一次(这是CGI最为人诟病的fork-and-execute 模式),这样一来在大规模并发下,就会挂掉。
四、FastCGI 协议
1. 概念
FastCGI 是CGI的升级版,也是一种通信协议,它是用来提高CGI程序性能的。
2. 特点
FastCGI 的特点是会在一个进程中依次完成多个请求,以达到提高效率的目的,大多数FastCGI 实现都会维护一个进程池。
3. 工作原理
1) Web Server启动时载入FastCGI进程管理器(IIS ISAPI或Apache Module)
2) FastCGI进程管理器自身初始化,启动多个CGI解释器进程(多个 PHP-CGI ) 并等待来自Web Server的连接。
3) 当客户端请求到达Web Server时,FastCGI进程管理器选择并连接到一个 CGI 解释器。Web Server将 CGI 环境变量和标准输入发送到FastCGI子进程 PHP-CGI。
4) FastCGI 子进程完成处理后将标准输出和错误信息从同一连接返回 Web Server。当FastCGI子进程关闭连接时,请求便处理完成。FastCGI子进程接着等待并处理来自进程管理器(运行在Web Server中)的下一个连接。 在CGI模式中,PHP-CGI 在此便退出了。
FASTCGI与CGI的区别:
在上述情况中,你可以想象CGI通常有多慢。每一个Web请求,PHP都必须重新解析php.ini、重新载入全部扩展并重新初始化全部数据结构。
使用FastCGI,所有这些都只在进程启动时发生一次。一个额外的好处是,持续数据库连接(Persistent database connection)可以工作。
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系统)不会摆弄它,只好继续用老式的那个。
七、总结
最后,我们来总结一下,这些技术经过不断的升级,可以解决什么问题(不然也不会升级嘛)。
所以,如果要搭建一个高性能的PHP WEB服务器,目前最佳的方式是Apache/Nginx + FastCGI + PHP-FPM(+PHP-CGI)方式了,不要再使用 Module加载或者 CGI 方式啦。
参考链接:
https://segmentfault.com/q/1010000000256516
http://www.nowamagic.net/librarys/veda/detail/1319
https://www.awaimai.com/371.html
https://www.jianshu.com/p/64e52f6f4837
http://rango.swoole.com/