Heim >Backend-Entwicklung >PHP-Tutorial >如何通俗地解释 CGI、FastCGI、php-fpm 之间的关系?

如何通俗地解释 CGI、FastCGI、php-fpm 之间的关系?

WBOY
WBOYOriginal
2016-06-06 16:43:111160Durchsuche

在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 协议的一个实现。

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后端的伪代码
<code class="language-text">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);
}
</code>
CGI 中文翻译是通用网关接口,它是一种通信协议,让脚本语言(比如PHP)具备和 HTTP Server 交互的能力。

FastCGI 是对 CGI 的一种改良,解决了 CGI 协议的一些性能问题,在 PHP 平台被广泛采用。类似的东西还有 WSGI。

php-fpm 就是FastCGI 的一种实现,附带了进程管理的功能。 CGI看RFC3875: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 会使用新的配置。
CGI,Common Gateway Interface,通用网关接口。将用户的指令通过它递交给后台进行处理。可以理解为一种通用的协议,能够标准化用户指令,方便后台程序进行后续的处理。

FastCGI根据协议将CGI进行包装,与外部程序如nginx进行通信。一般拥有主从进程。FastCGI可以管理多种语言的CGI,比如题主提到的PHP,另外还有Python、Ruby等。可以理解为一种CGI的成熟模型。

而PHP-FPM是一个很好地实现了FastCGI的程序,后来被PHP收入官方项目中了。可以理解为FastCGI的管理器。稳定地管理FastCGI进程。
Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn