学习CGI、FastCGI和PHP-FPM

0xGeekCat · 2020-8-16 · 次阅读


专有名词解释

  • CGI:Web Server与Web Application之间数据交换的一种协议。
  • FastCGI:同CGI,是Web Server与Web Application之间数据交换的一种通信协议,但比CGI在效率上做了一些优化。SCGI协议与FastCGI类似。
  • PHP-CGI:PHP对Web Server提供的CGI协议的接口程序。
  • PHP-FPM:PHP对Web Server提供的FastCGI协议的接口程序,额外还提供了相对智能一些任务管理
  • Web Server:Apache、Nginx、IIS、Lighttpd、Tomcat等服务器
  • Web Application:PHP、Java、Asp.net等应用程序

Module方式

在了解CGI之前,先了解一下Web server传递数据的另外一种方法:PHP模块加载

以Apache为例,在Apache的配置文件httpd.conf中进行配置👇

LoadModule php7_module libexec/apache2/libphp7.so

这种方式是用LoadModule来加载php7_module,就是把php作为apache的一个子模块来运行,当通过web服务访问php文件时,apache就会调用php7_module来解析php代码

php7_module通过sapi将数据传给php解析器来解析php代码

👇简单了解一下apache,php与sapi的关系

截屏2020-08-16 上午10.18.43

可以看出sapi是一个中间过程,sapi提供了一个和外部通信的接口,有点类似于socket,使得php可以和web server进行交互数据。php默认提供了很多种sapi,常见的提供给apache和nginx的php5_module、CGI、FastCGI,给IIS的ISAPI,以及Shell的CLI

补充说明: httpd是Apache服务器的主程序,被设计为一个独立运行的后台进程

👇apache调用php执行的过程

apache -> httpd -> php7_module -> sapi -> php

php模块加载将php模块安装到apache中,所以每次apache结束请求,都会产生一条完整包括php的各种运算计算等操作的进程

apache每接收一个请求,都会产生一个httpd进程来连接php通过sapi来完成请求,所以一旦用户过多导致并发数过多,服务器就会承受不住;而且把php模块编进apache,出现问题很难定位是php还是apache的问题

CGI - 通用网关接口

WEB服务器与PHP应用进行”交谈”的一种工具,其程序须运行在web server上。CGI可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量。如php、perl、tcl等

👇CGI的工作原理

当web服务器收到客户端http请求后,会启动对应的CGI程序。接下来PHP解析器会解析php.ini,初始化执行环境,然后处理请求,也就是俗称的fork-and-execute(这个在请求量大时,会到时严重问题);再以CGI规定的格式返回处理后的结果,退出进程,Web server再把结果返回给浏览器

CGI的好处就是完全独立于任何服务器,仅仅是做为中间分子。web server和web application通过cgi搭线来完成数据传递。尽量减少二者关联,使二者更独立;但是CGI也具有一个严重问题就是并发性差,因为之前提到面对执行每次请求都会初始化执行环境

FastCGI - 快速通用网关接口

FastCGI是用来提高CGI程序性能的。类似于CGI,FastCGI也可以说是一种协议;像是一个常驻型的CGI,可以一直执行着。它还支持分布式运算, 即FastCGI程序可以在网站服务器以外的主机上执行,并接受来自其它网站服务器的请求;FastCGI是语言无关的、可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中,并因此获得较高的性能。众所周知CGI解释器的反复加载是CGI性能低下的主要原因,如果CGI解释器保持在内存中,并接受FastCGI进程管理器调度,则可以提供良好的性能、伸缩性、Fail - Over特性等

👇FastCGI的工作原理

FastCGI接口方式采用C/S结构,可以将web服务器和脚本解析器分开,同时在脚本解析器上启动一个或者多个脚本解析守护进程。当web服务器每次遇到动态程序时,可以将其直接交付给FastCGI进程来执行,然后将得到的结果返回给浏览器,这在很大程度上提高了整个应用系统的性能

截屏2020-08-16 上午11.04.18

  1. Web Server启动时载入FastCGI进程管理器
  2. FastCGI进程管理器自身初始化,启动多个CGI解释器进程,并等待来自Web Server的连接
  3. 当客户端请求到达Web Server时,FastCGI进程管理器选择并连接到一个CGI解释器。Web server将CGI环境变量和标准输入发送到FastCGI子进程php-cgi
  4. FastCGI子进程完成处理后,将标准输出和错误信息从同一连接返回Web Server
  5. FastCGI子进程关闭连接,等待运行在Web Server中的FastCGI进程管理器的下一个连接

FastCGI与CGI特点

  • 拿php web举例,每一个Web请求都必须重新解析php.ini、载入全部扩展,并初始化全部数据结构。而使用FastCGI,所有这些都只在进程启动时发生一次
  • 由于FastCGI是多进程,所以比CGI多线程消耗更多的服务器内存

PHP-FPM - FastCGI进程管理器

要了解PHP-FPM,就得先了解PHP-CGI,PHP-CGI就是PHP自带的FastCGI管理器

虽然是php官方出品,但性能太差,而且也很麻烦不人性化,具体体现👇

  • php-cgi变更php.ini配置后,需重启php-cgi才能让新的php-ini生效,不可以平滑重启
  • 直接杀死php-cgi进程,php就不能运行

上面两个问题一直让人病垢。 直到PHP-FPM的出现,这是一个PHP专用的FastCGI管理器,它克服了上面两个问题,而且在其他方面更强劲

也就是说,PHP-FPM是对于FastCGI协议的具体实现,他负责管理一个进程池,来处理来自Web服务器的请求

因为php-cgi只是个CGI程序,本身只能解析请求返回结果,不会进程管理。所以就出现了一些能够调度php-cgi进程的程序。PHP-FPM就是用于调度管理PHP解析器php-cgi的管理程序

截屏2020-08-16 上午9.39.22

技术升级

截屏2020-08-16 上午11.36.08

如果要搭建一个高性能的PHP WEB服务器,目前最佳的方式是Apache/Nginx + FastCGI + PHP-FPM

reference

CGI、FastCGI和PHP-FPM关系图解

郑重感谢