CGI、FastCGI和php-fpm概念和区别
cgi:
CGI的英文是(COMMON GATEWAY INTERFACE)公共网关接口,它的作用就是帮助服务器与语言通信,它是Web服务器与外部应用程序(CGI程序)之间传递信息的接口标准。这里就是nginx和php进行通信,因为nginx和php的语言不通,因此需要一个沟通转换的过程,而CGI就是这个沟通的协议。
nginx服务器在接受到浏览器传递过来的数据后,如果请求的是静态的页面或者图片等无需动态处理的则会直接根据请求的url找到其位置然后返回给浏览器,这里分发的是静态数据,这里无需php参与。但是如果是一个动态的页面请求(例如:/index.php),这个时候nginx就必须与php通信,这个时候就会需要用到cgi协议,将请求数据转换成php能理解的信息,然后php根据这些信息返回的信息也要通过cgi协议转换成nginx可以理解的信息,最后nginx接到这些信息再返回给浏览器。
CGI就是规定客户端向web server请求数据的时候,要传哪些数据、以什么样的格式传递的一种协议。
通过CGI接口,Web服务器就能够获取客户端提交的信息,并转交给服务器端的CGI程序处理,最后返回结果给客户端。一般地,我们提到的CGI实际上是实现了CGI接口标准的程序,用来处理客户请求。CGI程序可以用C、perl、php等来编写。
以前,web服务器一般只处理静态的请求,如果碰到一个动态请求,web服务器会根据这次请求的内容,然后fork一个进程启动CGI程序,这里就是指PHP的解析器,PHP解析器程序启动后,它就会解析php.ini文件,初始化执行环境,然后解析动态脚本,再把处理完的数据返回给web服务器,最后web服务器把内容发送给用户,刚才fork的进程也随之退出。 如果下次用户还请求改动态脚本,那么web服务器又再次fork一个新的子进程启动CGI程序,周而复始的进行。启动CGI程序需要读取配置文件、加载相关扩展等,这样的工作效率非常低下。
fast-cgi:
传统的cgi协议在每次连接请求时,会开启一个进程进行处理,处理完毕会关闭该进程,因此下次连接,又要再次开启一个进程进行处理,因此有多少个连接就有多少个cgi进程,这也就是为什么传统的cgi会显得缓慢的原因,因此过多的进程会消耗资源和内存。
而fast-cgi则是一个进程可以处理多个请求,和上面的cgi协议完全不一样,cgi是一个进程只能处理一个请求,这样就会导致大量的cgi程序,因此会给服务器带来负担。
fast-cgi 运行流程
(1)Web Server启动时载入FastCGI进程管理器(Apache Module或IIS ISAPI等)
(2)FastCGI会先启一个master,解析配置文件,初始化执行环境,然后启动多个CGI解释器进程(php-cgi,即worker),并等待来自Web Server的连接。
(3)当客户端请求到达Web Server时,FastCGI进程管理器选择并连接到一个CGI解释器(即分配给一个worker)。然后立即可以接受下一个请求。这样就避免了重复的劳动,效率自然是高。而且当worker不够用时,master可以根据配置预先启动几个worker等着;当然空闲worker太多时,也会停掉一些,这样就提高了性能,也节约了资源。这就是fastcgi的对进程的管理。
(4)FastCGI子进程完成处理后,将标准输出和错误信息从同一连接返回Web Server。当FastCGI子进程关闭连接时,请求便告处理完成。FastCGI子进程接着等待,并处理来自FastCGI进程管理器(运行在Web Server中)的下一个连接。(在CGI模式中,php-cgi在此便推出了)
php-cgi:
php-cgi是php提供给web serve也就是http前端服务器的cgi协议接口程序,当每次接到http前端服务器的请求都会开启一个php-cgi进程进行处理,而且开启的php-cgi的过程中会先要重载配置,数据结构以及初始化运行环境,如果更新了php配置,那么就需要重启php-cgi才能生效,例如phpstudy就是这种情况。
php-fpm:
php-fpm是php提供给web serve也就是http前端服务器的fastcgi协议接口程序,它不会像php-cgi一样每次连接都会重新开启一个进程,处理完请求又关闭这个进程,而是允许一个进程对多个连接进行处理,而不会立即关闭这个进程,而是会接着处理下一个连接。它可以说是php-cgi的一个管理程序,是对php-cgi的改进。
php-fpm会开启多个php-cgi程序,并且php-fpm常驻内存,每次web serve服务器发送连接过来的时候,php-fpm将连接信息分配给下面其中的一个子程序php-cgi进行处理,处理完毕这个php-cgi并不会关闭,而是继续等待下一个连接,这也是fast-cgi加速的原理,但是由于php-fpm是多进程的,而一个php-cgi基本消耗7-25M内存,因此如果连接过多就会导致内存消耗过大,引发一些问题,例如nginx里的502错误。
同时php-fpm还附带一些其他的功能:
例如平滑过渡配置更改,普通的php-cgi在每次更改配置后,需要重新启动才能初始化新的配置,而php-fpm是不需要,php-fpm分将新的连接发送给新的子程序php-cgi,这个时候加载的是新的配置,而原先正在运行的php-cgi还是使用的原先的配置,等到这个连接后下一次连接的时候会使用新的配置初始化,这就是平滑过渡。
Web服务器内置模块
由于以CGI程序处理动态请求的工作模式效率非常低,因此出现了较高效的方式:Web服务器内置模块,如apache的mod_php模块、微软iis的ISAPI、nginx的php-fpm,将php解释器做成模块加载到服务器中。这样,随着服务器的启动,PHP解释器模块也会随之启动。不用像上面的那种方式每处理一个动态请求就要启动一次CGI程序,而是在服务器启动时,读取php配置文件,加载php模块。
此外,mod_php 通过嵌入 PHP 解释器到 Apache 进程中,只能与 Apache 配合使用,而 cgi 和 fast-cgi 以独立的进程的形式出现,只要对应的Web服务器实现 cgi 或者 fast-cgi 协议,就能够处理 PHP 请求。mod_php 这种嵌入的方式最大的弊端就是内存占用大,不论是否用到 PHP 解释器都会将其加载到内存中。