一、网关背景知识
我们在使用浏览器请求服务器的时候,最终执行请求处理的是 WEB服务器如:nginx、tomcat、iis、apache等;如果我们在浏览器中请求的是静态的网页如:index.html、w3capi.html等,则WEB服务器可以直接将静态页面进行响应返回到浏览器中,但是如果请求的是动态脚本如:idex.php、index.aspx、index.jsp等,WEB服务器会根据配置发现我们请求的不是静态文件资源,而是动态文件资源,需要请求其他相关的后端服务对此动态文件进行解析并返回。那么,WEB服务器在请求相关后端服务时,需要以什么样的格式、什么样的方式、发送给后端服务什么样的数据呢?在PHP执行环境中,其实是通过CGI进行处理的。CGI就是定义文件格式、数据内容的接口协议。
CGI 就是WEB服务器如:nginx、tomcat、iis、apache,跟动态脚本语言如:PHP、.Net、Java等,通信的协议接口。下面我们针对这几个名词进行一一解析。
二、CGI
CGI是通用网关接口(Common Gateway Interface)是一种重要的互联网技术,可以让一个客户端,从网页浏览器向执行在网络服务器上的程序请求数据。CGI描述了服务器和请求处理程序之间传输数据的一种标准。
CGI使外部程序与Web服务器之间交互成为可能。CGI程序运行在独立的进程中,并对每个Web请求建立一个进程,这种方法非常容易实现,但效率很差,难以扩展。面对大量请求,进程的大量建立和消亡使操作系统性能大大下降。此外,由于地址空间无法共享,也限制了资源重用。
对于PHP来说,使用CGI协议的WEB服务器,每次在请求后端服务解析动态文件时,都要启动实现CGI协议的程序,这里就是PHP解析器。PHP解析器会解析PHP.ini文件,进行初始化工作,处理请求、返回结果。由于每个请求都要重新初始化,执行效率太低。所以,FCGI应运而生。 因为PHP是解释型语言,因此需要解释器去解释PHP代码。
三、FCGI:fast common gateway interface 快速通用网关接口
快速通用网关接口(Fast Common Gateway Interface)是一种让交互程序与Web服务器通信的协议。FastCGI是早期通用网关接口(CGI)的增强版本。FastCGI致力于减少网页服务器与CGI程序之间互动的开销,从而使服务器可以同时处理更多的网页请求。
与为每个请求创建一个新的进程不同,FastCGI使用持续的进程来处理一连串的请求。这些进程由FastCGI服务器管理,而不是web服务器。 当进来一个请求时,web服务器把环境变量和这个页面请求通过一个socket比如FastCGI进程与web服务器(都位于本地)或者一个TCP connection(FastCGI进程在远端的server farm)传递给FastCGI进程。
FCGI协议的应用程序的实现原理,它首先会启动一个master进程,master基础用来解析PHP.ini文件,进行初始化工作。然后再启动多个worker进程,worker进程用来处理具体的请求。这样将初始化和处理具体的请求就分离了。这样也就需要一个程序来管理master和worker,所以PHP-FPM就出现了。
- FCGI采用C/S架构方式。将WEB服务器与脚本解析服务器分离开来。使得WEB服务器只需要处理静态资源,对于动态文件资源则请求后端脚本解析服务器,将解析服务器返回的数据返回给浏览器。
- WEB服务器,如nginx则不支持对外部程序如PHP程序,的直接调用或者解析,因此必须通过CGI接口来调用。这是其实需要将CGI进行一个封装,形成一个wrapper,其实就是PHP-FPM。nginx调用PHP-FPM,PHP-FPM再调用后端的PHP代码,然后PHP-FPM返回结果给nginx进行请求响应。
- 现在PHP-FPM已经被集成到PHP内核中。
- PHP-FPM与nginx经常会部署在不同服务器上,以减轻前端nginx处理静态资源,转发动态请求的压力。
- FCGI也比CGI要安全。
四、PHP-FPM:PHP-Fast CGI Process Manager
如果修改了php.ini文件,PHP-CGI是无法平滑过渡的。也就是,必须要重启PHP-CGI程序才能使用这些新的配置。
如果修改了php.ini文件,PHP-FPM可以实现平滑过渡。对于修改之前的worker,当处理完这次请求之后,会对其进行销毁,新生成的worker可以使用新的配置。这样也就实现了平滑过渡。 而且,如果PHP-CGI进程挂了,PHP也就不能运行了。PHP-FPM没有这个问题,守护进程会平滑重新启动一个子进程。
PHP-FPM在出现之前,其实有个从lighthttpd发展来的spawn-fcgi。PHP-FPM可以在初始化时创建多个worker,当有worker空闲时,可以对worker进行回收。spawn-fcgi在高并发时会出现内存泄漏、甚至自动重启FCGI的问题。
php-cgi与php-fpm一样,也是一个fastcgi进程管理器,php-cgi的问题在于 1、php-cgi变更php.ini配置后需重启php-cgi才能让新的php-ini生效,不可以平滑重启;2、直接杀死php-cgi进程,php就不能运行了。(PHP-FPM和Spawn-FCGI就没有这个问题,守护进程会平滑从新生成新的子进程。) 针对php-cgi的不足,php-fpm应运而生。
五、CGI概念总结
- CGI 和 FastCGI 是一种通信协议规范,不是一个实体
- CGI 程序和FastCGI程序,是指实现这两个协议的程序,可以是任何语言实现这个协议的。(PHP-CGI 和 PHP-FPM就是实现FastCGI的程序)
- FastCGI为了提高CGI的效率而存在的
- PHP-CGI是PHP自带的FastCGI管理器
- PHP-FPM 的管理对象是php-cgi。使用PHP-FPM来控制PHP-CGI的FastCGI进程
- php-cgi是CGI协议的实现,PHP-FPM是FCGI协议的实现