如何通俗地解释 CGI、FastCGI、php-fpm 之间的关系?
程序员文章站
2022-05-23 12:55:25
...
在apache里,可以以php5_module模块的方式调用PHP,而在nginx里面,则需要通过php-fpm来调用,这两种调用方式有什么不同?另外,它们跟cgi,fastcgi有什么关系?
CGI是HTTP Server和一个独立的进程之间的协议,把HTTP Request的Header设置成进程的环境变量,HTTP Request的正文设置成进程的标准输入,而进程的标准输出就是HTTP Response包括Header和正文。
FASTCGI是和HTTP协议类似的概念。无非就是规定了在同一个TCP连接里怎么同时传多个HTTP连接。这实际上导致了个问题,有个HTTP连接传个大文件不肯让出FASTCGI连接,在同一个FASTCGI连接里的其他HTTP连接就傻了。所以Lighttpd? 引入了 X-SENDFILE 。
php-fpm就相当于是Apache+mod_php。无非php-fpm自带了FASTCGI Server,而Apache是HTTP Server。
那个WSGI和这个问题没啥关系吧。WSGI这个只是Python内部的一个接口。无论你前面是FASTCGI,HTTP,SCGI,uWSGI等协议,你的FASTCGI/HTTP/SCGI/uWSGI Server都以相同的参数格式去调用一个函数,这样你用Python写的Web应用并不需要修改代码,就可以运行在不同的Server后面了。无非CGI协议是进程间的,而WSGI是进程内的。 b本屌丝路过 也来吹吹牛逼
1. 一般web服务器接受到浏览器的请求时,如果是静态资源的话就直接将其返回给浏览器,如果是动态资源的话那就没有现成的资源返回了,那这个时候cgi就出场了
2. cgi可以理解为一种协议or一类处理程序,就是动态去生成文件,从程序上来理解就是web服务器exec这样一个进程,然后交给他一些输入参数,他就慢慢的处理完后把结果返回给web服务器,那从协议层面来说cgi协议就是规范了web服务器和cgi程序的一些输入输出参数的含义
3.所以可以有很多不同的cgi程序,别可以执行php脚本的or可以执行python脚本的,只要符合这类规范就能供web服务器调用,当然它的缺点就是每次都需要去启动这个cgi程序,这会使得处理速度很慢
4.针对这种缺陷加以改进就成了fastcgi,同样的他也可以理解为一种协议or一个程序,它跟cgi的不同就是不需要每次去exec,它会事先启动起来,作为一个cgi的管理服务器存在,预先启动一系列的子进程来等待处理,然后等待web服务器发过来的请求,一旦接受到请求就交由子进程处理,这样由于不需要在接受到请求后启动cgi,会快很多。
5.phpfpm是php对fastcgi的一种具体实现,它的启动后会创建多个cgi子进程,然后主进程负责管理子进程,同时它对外提供一个socket,那web服务器当要转发一个动态请求时只需要按照fastcgi协议要求的格式将数据发往这个socket的就可以了,那phpfpm创建的子进程去争抢这个socket连接,谁抢到了谁处理并将结果返回给web服务器,那phpfpm主进程干什么了?比方说其中一个子进程异常退出了怎么办,那phpfpm会去监控他一旦发现一个cgi子进程就会又启动一个,还有其他诸多管理功能
6 phpfpm作为一个独立的进程存在 通过socket与nginx建立连接,而mod_php 是作为一个模块被加载进了apache服务器,同时他们两作为cgi调度管理器,他们对其管理的方式也不一样
就说这么多了 通俗的可以把服务器看作餐厅,用户请求看作来用餐的顾客,服务器处理请求看作解决顾客的就餐问题(响应输出一份饭)。
服务器上静态资源看作已做好的饭,只要放到餐盒里就可以返回给顾客,动态资源需要厨房大厨现成做份再放到餐盒里返回给顾客。
php_mod这个大厨有个特点,看见有顾客进门就点火,不管顾客要不要现做的,有点浪费资源
php_fpm这个大厨有好多小弟一直点着火(多个处理进程),等有顾客说要现做,大厨就安排小弟做份返回给客户
cgi也是个大厨,不过他等到顾客要现做,他才点火,做饭,然后熄火。等待下一个要现做的到来
fastcgi呢就是个大厨雇了一帮小弟,专门做需要现场做的饭,大厨只管分派任务,小弟真正操锅做饭 这个问题可以分两个层面讨论:
1. PHP 解释器是否嵌入 Web 服务器进程内部执行
mod_php 通过嵌入 PHP 解释器到 Apache 进程中,只能与 Apache 配合使用,而 cgi 和 fast-cgi 以独立的进程的形式出现,只要对应的Web服务器实现 cgi 或者 fast-cgi 协议,就能够处理 PHP 请求。
mod_php 这种嵌入的方式最大的弊端就是内存占用大,不论是否用到 PHP 解释器都会将其加载到内存中,典型的就是处理CSS、JS之类的静态文件是完全没有必要加载解释器。
2. 单个进程处理的请求数量
mod_php 和 fast-cgi 的模式在每个进程的生命周期内能够处理多个请求,而 cgi 的模式处理一个请求就马上销毁进程,在高并发的场景下 cgi 的性能非常糟糕。
综上,如果对性能有极高的要求,可以将静态请求和动态请求分开,这时 Nginx + php-fpm 是比较好的选择。
PS: cgi、fastcgi 通常指 Web 服务器与解释器通信的协议规范,而 php-fpm 是 fastcgi 协议的一个实现。
FastCGI 是对 CGI 的一种改良,解决了 CGI 协议的一些性能问题,在 PHP 平台被广泛采用。类似的东西还有 WSGI。
php-fpm 就是FastCGI 的一种实现,附带了进程管理的功能。 CGI看RFC3875:https://www.ietf.org/rfc/rfc3875
FastCGI看:FastCGI Specification
总的来说FastCGI是对CGI的性能改进,规范上有一些差异但是不大,与浏览器的通信规范是一致的。
PHP不了解。
php-cgi 是一种CGI 协议的实现。
php-fpm 即FastCGI Process Management,是一种FastCGI 协议的实现。
FastCGI根据协议将CGI进行包装,与外部程序如nginx进行通信。一般拥有主从进程。FastCGI可以管理多种语言的CGI,比如题主提到的PHP,另外还有Python、Ruby等。可以理解为一种CGI的成熟模型。
而PHP-FPM是一个很好地实现了FastCGI的程序,后来被PHP收入官方项目中了。可以理解为FastCGI的管理器。稳定地管理FastCGI进程。
回复内容:
上面的回答多少都有些问题吧。CGI是HTTP Server和一个独立的进程之间的协议,把HTTP Request的Header设置成进程的环境变量,HTTP Request的正文设置成进程的标准输入,而进程的标准输出就是HTTP Response包括Header和正文。
FASTCGI是和HTTP协议类似的概念。无非就是规定了在同一个TCP连接里怎么同时传多个HTTP连接。这实际上导致了个问题,有个HTTP连接传个大文件不肯让出FASTCGI连接,在同一个FASTCGI连接里的其他HTTP连接就傻了。所以Lighttpd? 引入了 X-SENDFILE 。
php-fpm就相当于是Apache+mod_php。无非php-fpm自带了FASTCGI Server,而Apache是HTTP Server。
那个WSGI和这个问题没啥关系吧。WSGI这个只是Python内部的一个接口。无论你前面是FASTCGI,HTTP,SCGI,uWSGI等协议,你的FASTCGI/HTTP/SCGI/uWSGI Server都以相同的参数格式去调用一个函数,这样你用Python写的Web应用并不需要修改代码,就可以运行在不同的Server后面了。无非CGI协议是进程间的,而WSGI是进程内的。 b本屌丝路过 也来吹吹牛逼
1. 一般web服务器接受到浏览器的请求时,如果是静态资源的话就直接将其返回给浏览器,如果是动态资源的话那就没有现成的资源返回了,那这个时候cgi就出场了
2. cgi可以理解为一种协议or一类处理程序,就是动态去生成文件,从程序上来理解就是web服务器exec这样一个进程,然后交给他一些输入参数,他就慢慢的处理完后把结果返回给web服务器,那从协议层面来说cgi协议就是规范了web服务器和cgi程序的一些输入输出参数的含义
3.所以可以有很多不同的cgi程序,别可以执行php脚本的or可以执行python脚本的,只要符合这类规范就能供web服务器调用,当然它的缺点就是每次都需要去启动这个cgi程序,这会使得处理速度很慢
4.针对这种缺陷加以改进就成了fastcgi,同样的他也可以理解为一种协议or一个程序,它跟cgi的不同就是不需要每次去exec,它会事先启动起来,作为一个cgi的管理服务器存在,预先启动一系列的子进程来等待处理,然后等待web服务器发过来的请求,一旦接受到请求就交由子进程处理,这样由于不需要在接受到请求后启动cgi,会快很多。
5.phpfpm是php对fastcgi的一种具体实现,它的启动后会创建多个cgi子进程,然后主进程负责管理子进程,同时它对外提供一个socket,那web服务器当要转发一个动态请求时只需要按照fastcgi协议要求的格式将数据发往这个socket的就可以了,那phpfpm创建的子进程去争抢这个socket连接,谁抢到了谁处理并将结果返回给web服务器,那phpfpm主进程干什么了?比方说其中一个子进程异常退出了怎么办,那phpfpm会去监控他一旦发现一个cgi子进程就会又启动一个,还有其他诸多管理功能
6 phpfpm作为一个独立的进程存在 通过socket与nginx建立连接,而mod_php 是作为一个模块被加载进了apache服务器,同时他们两作为cgi调度管理器,他们对其管理的方式也不一样
就说这么多了 通俗的可以把服务器看作餐厅,用户请求看作来用餐的顾客,服务器处理请求看作解决顾客的就餐问题(响应输出一份饭)。
服务器上静态资源看作已做好的饭,只要放到餐盒里就可以返回给顾客,动态资源需要厨房大厨现成做份再放到餐盒里返回给顾客。
php_mod这个大厨有个特点,看见有顾客进门就点火,不管顾客要不要现做的,有点浪费资源
php_fpm这个大厨有好多小弟一直点着火(多个处理进程),等有顾客说要现做,大厨就安排小弟做份返回给客户
cgi也是个大厨,不过他等到顾客要现做,他才点火,做饭,然后熄火。等待下一个要现做的到来
fastcgi呢就是个大厨雇了一帮小弟,专门做需要现场做的饭,大厨只管分派任务,小弟真正操锅做饭 这个问题可以分两个层面讨论:
1. PHP 解释器是否嵌入 Web 服务器进程内部执行
mod_php 通过嵌入 PHP 解释器到 Apache 进程中,只能与 Apache 配合使用,而 cgi 和 fast-cgi 以独立的进程的形式出现,只要对应的Web服务器实现 cgi 或者 fast-cgi 协议,就能够处理 PHP 请求。
mod_php 这种嵌入的方式最大的弊端就是内存占用大,不论是否用到 PHP 解释器都会将其加载到内存中,典型的就是处理CSS、JS之类的静态文件是完全没有必要加载解释器。
2. 单个进程处理的请求数量
mod_php 和 fast-cgi 的模式在每个进程的生命周期内能够处理多个请求,而 cgi 的模式处理一个请求就马上销毁进程,在高并发的场景下 cgi 的性能非常糟糕。
综上,如果对性能有极高的要求,可以将静态请求和动态请求分开,这时 Nginx + php-fpm 是比较好的选择。
PS: cgi、fastcgi 通常指 Web 服务器与解释器通信的协议规范,而 php-fpm 是 fastcgi 协议的一个实现。
CGI(Common Gateway Interface)
最初,CGI 是在 1993 年由美国国家超级电脑应用中心(NCSA)为 NCSA HTTPd Web 服务器开发的。
这个 Web 服务器使用了 UNIX shell 环境变量 来保存从 Web 服务器传递出去的参数,然后生成一个运行 CGI 的独立进程。CGI的第一个实现是 Perl 写的[1]。
- 效率低下:每一个连接 fork 一个进程处理。
- 功能十分有限:CGI只能收到一个请求,输出一个响应。很难在CGI体系去对Web请求的控制,例如:用户认证等。
正因为这些问题,在CGI诞生后的很长一段时间,各种Web Server都还是采用API这种强绑定的方式去支持Web开发,其中Apache的mod_php就属于这种方式。所以后面就有大神提出了FastCGI标准。
FastCGI(Fast Common Gateway Interface)
FastCGI使用进程/线程池来处理一连串的请求。这些进程/线程由FastCGI服务器管理,而不是Web服务器。 当进来一个请求时,Web服务器把环境变量和这个页面请求通过一个Socket长连接传递给FastCGI进程。所以FastCGI有如下的优点:
- 性能:通过进程/线程池规避了CGI开辟新的进程的开销。
- 兼容:非常容易改造现有CGI标准的程序。
- 语言无关:FastCGI是一套标准,理论上讲只要能进行标准输出(stdout)的语言都可以作为FastCGI标准的Web后端。
下面是一个简单FastCGI后端的伪代码
void main(void)
{
int count = 0;
while(FCGI_Accept() >= 0) {
printf(“Content-type: text/html\r\n”);
printf(“\r\n”);
printf(“Hello world!\r\n”);
printf(“Request number %d.”, count++);
}
exit(0);
}
CGI 中文翻译是通用网关接口,它是一种通信协议,让脚本语言(比如PHP)具备和 HTTP Server 交互的能力。FastCGI 是对 CGI 的一种改良,解决了 CGI 协议的一些性能问题,在 PHP 平台被广泛采用。类似的东西还有 WSGI。
php-fpm 就是FastCGI 的一种实现,附带了进程管理的功能。 CGI看RFC3875:https://www.ietf.org/rfc/rfc3875
FastCGI看:FastCGI Specification
总的来说FastCGI是对CGI的性能改进,规范上有一些差异但是不大,与浏览器的通信规范是一致的。
PHP不了解。
PHP 解释器的执行,主要有三者模式,mod_php、CGI、FastCGI。
- mode_php 是Apache 的一个模块,把PHP 解释器嵌入到Apache 进程中。
- CGI 和FastCGI 分别是一种协议。Web Server 实现了CGI 或FastCGI 协议的相应的应用程序(以下简称CGI 或FastCGI),就可以启动PHP 解释器处理PHP 请求。它们都是以独立进程的形式存在。
- mode_php 和FastCGI 在 单个进程中可以处理多个请求,CGI 在单个进程中只能处理一个请求。
php-cgi 是一种CGI 协议的实现。
- php-cgi 其实就是PHP 解析器。
- 在CGI 模式时,当Web Server 收到 xx/index.php 请求时,会启动php-cgi,php-cgi 会解析php.ini 文件,初始化环境,然后根据请求参数进行处理,再返回处理后的结果。(都是以CGI 协议规范来进行)
- php-cgi 在每个请求时都会启动一个进程,然后读取php.ini 进行解析,可想而知效率相对比较低。
- php-cgi 无法实现平滑重启。修改php.ini 配置后,后面启动的php-cgi 程序还是不会感知。
php-fpm 即FastCGI Process Management,是一种FastCGI 协议的实现。
- 当请求到来时,php-fpm 启动并读取php.ini 文件完成初始化环境,然后启动一个master,再启动多个worker。当请求过来时,master 会传递给一个worker,然后等待下一个请求。php-fpm 会动态配置worker 的数量。
- 一个php-fpm 进程可以处理多个请求,会启动多个php-cgi 程序。
- php-fpm 可以实现平衡重启。修改php.ini 后,当启用新的worker 会使用新的配置。
FastCGI根据协议将CGI进行包装,与外部程序如nginx进行通信。一般拥有主从进程。FastCGI可以管理多种语言的CGI,比如题主提到的PHP,另外还有Python、Ruby等。可以理解为一种CGI的成熟模型。
而PHP-FPM是一个很好地实现了FastCGI的程序,后来被PHP收入官方项目中了。可以理解为FastCGI的管理器。稳定地管理FastCGI进程。
声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
相关文章
相关视频