Skip to content

CGI、PHP-CGI、FastCGI和PHP-FPM关系以及实际应用

约 2627 字大约 9 分钟

PHP

2024-10-30

前言

近期在部署一些cms,搭建LAMP/LNMP 服务器时,配置期间频繁遇到这几个概念,恰好新生刚接触phpstudy,如果不知道相关知识,后期很难顺利搭建部署服务,前期学习也会对php网站的原理一知半解,至于安全方面会涉及一些ssrf,以及php-cgi的漏洞(CVE-2024-4577),不过这篇文章不分析安全部分,只借鉴一些优秀文章的图解来讲解基础的概念及联系。

基础

Web 服务器(如 Apache、Nginx)主要负责将内容分发给客户端,尤其是静态资源的分发,例如 .html.css.js 文件以及图片、视频等文件。

  • 对于静态请求,它的工作流程相对简单:
  1. 接收请求:客户端(如浏览器)向服务器发出请求,比如请求 index.html
  2. 处理请求:Web 服务器解析请求,找到对应的资源路径。在这里,index.html 文件的位置通常是服务器的根目录下的一个文件。
  3. 查找文件:服务器在文件系统中查找该文件。如果找到,就将文件内容读取出来;如果找不到,则返回 404 错误。
  4. 返回内容:将文件内容(HTML 页面内容)通过 HTTP 响应发送给客户端,浏览器接收后就可以渲染页面了。

这种静态数据的分发不需要任何后台逻辑处理或数据库查询,所以它的处理速度相对较快。

image-20241030145911894

  • 对于动态 PHP 内容,Web 服务器(如 Apache 或 Nginx)需要与 PHP 解释器配合,将请求分发给 PHP 处理并返回生成的内容。具体流程如下:
  1. 接收请求:客户端(浏览器)请求动态资源,例如 index.php。这个请求通过 HTTP 协议到达 Web 服务器。
  2. 识别动态内容:Web 服务器识别到 .php 文件的请求,判断这是一个需要动态生成的页面,而不是直接可以返回的静态文件。
  3. 转发给 PHP 解释器:Web 服务器将请求传递给 PHP 解释器。具体方式依赖于 Web 服务器:
    • Apache:通常通过 mod_php 模块直接处理 PHP 请求,或通过 FastCGI 协议与 PHP-FPM 通信。
    • Nginx:使用 FastCGI 协议将请求转发给 PHP-FPM(PHP FastCGI Process Manager)。
  4. PHP 解释器处理请求
    • PHP 解释器解析 index.php 文件中的代码。
    • 如果 PHP 脚本需要访问数据库,则会通过数据库驱动(如 MySQLi、PDO)查询、更新数据等。
    • 执行 PHP 代码生成 HTML 输出或其他响应内容。
  5. 返回内容:PHP 解释器将生成的内容(通常是 HTML)返回给 Web 服务器。
  6. 发送响应:Web 服务器接收到 PHP 解释器的输出,将该内容作为 HTTP 响应发送回客户端。客户端的浏览器接收并渲染生成的页面。

image-20241030150120075

概念的简单描述:

  • **CGI:**是 Web Server 与 Web Application 之间数据交换的一种协议。
  • **FastCGI:**同 CGI,是一种通信协议,但比 CGI 在效率上做了一些优化。同样,SCGI 协议与 FastCGI 类似。
  • **PHP-CGI:**是 PHP (Web Application)对 Web Server 提供的 CGI 协议的接口程序。
  • **PHP-FPM:**是 PHP(Web Application)对 Web Server 提供的 FastCGI 协议的接口程序,额外还提供了相对智能一些任务管理。

WEB 中,

  • Web Server 一般指Apache、Nginx、IIS、Lighttpd、Tomcat等服务器,
  • Web Application 一般指PHP、Java、Asp.net等应用程序。

概念

CGI(Common Gateway Interface)

CGI(Common Gateway Interface,即“通用网关接口”)是一种用于 Web 服务器与后台应用程序(如 PHP 应用)之间通信的标准接口。该协议允许 Web 服务器将请求转发给后台应用程序,接收并处理其返回的结果。CGI 程序通常部署在 Web 服务器上,可以使用任何支持标准输入、输出和环境变量的编程语言实现,如 PHP、Perl、Tcl 等。

在 CGI 工作流程中,Web 服务器会将请求的相关数据传递给 CGI 程序,包括 URL、查询字符串、POST 数据及 HTTP 头信息。CGI 规定了 Web 服务器应如何将这些数据传递给后端应用程序,从而使应用能够处理请求并返回 HTML 或其他格式的响应内容。此流程使得 CGI 成为 Web 服务器与后台程序的接口,特别是 HTTP 请求参数的传递通道。

CGI 的设计优势在于其独立性,作为中间接口,它使 Web 服务器和应用程序能够各自独立运作,降低了彼此之间的耦合性。Web 服务器可以通过 CGI 与任何兼容的后台应用程序通信,而应用程序则无需依赖特定的 Web 服务器。

然而,CGI 的缺点在于其“fork-and-execute”执行模式。对于每个请求,Web 服务器都需要启动一个新的 CGI 进程,这包括初始化和销毁进程的开销。该模式在大规模并发请求场景中会导致服务器资源的严重消耗,从而影响性能。因此,传统 CGI 并不适合高并发场景。

FastCGI

为了解决上面CGI的缺点,FastCGI应运而生

从根本上来说,FastCGI是用来提高CGI程序性能的。类似于CGI,FastCGI也可以说是一种协议

FastCGI像是一个常驻(long-live)型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去fork一次。它还支持分布式的运算, 即 FastCGI 程序可以在网站服务器以外的主机上执行,并且接受来自其它网站服务器来的请求。

FastCGI是语言无关的、可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中,并因此获得较高的性能。众所周知,CGI解释器的反复加载是CGI性能低下的主要原因,如果CGI解释器保持在内存中,并接受FastCGI进程管理器调度,则可以提供良好的性能、伸缩性、Fail- Over特性等等。

FastCGI的工作原理

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

image-20241030151849155

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

FastCGI与CGI特点:

  1. 对于CGI来说,每一个Web请求PHP都必须重新解析php.ini、重新载入全部扩展,并重新初始化全部数据结构。而使用FastCGI,所有这些都只在进程启动时发生一次。一个额外的好处是,持续数据库连接(Persistent database connection)可以工作。
  2. 由于FastCGI是多进程,所以比CGI多线程消耗更多的服务器内存,php-cgi解释器每进程消耗7至25兆内存,将这个数字乘以50或100就是很大的内存数。

PHP-FPM

fastcgi是一个协议,php-fpm实现了这个协议。

PHP的解释器是php-cgi。php-cgi只是个CGI程序,他自己本身只能解析请求,返回结果,不会进程管理,所以就出现了一些能够调度php-cgi进程的程序,php-fpm就是这样的一个东西。它克服了php-cgi变更php.ini配置后,需重启php-cgi才能让新的php-ini生效,不可以平滑重启,直接杀死php-cgi进程,php就不能运行了的问题。PHP5.3版本之后,PHP-FPM是内置于PHP的。

总之就是php-fpm提供了更好的php进程管理方式,可以有效的控制内存和进程,可以平滑重载php配置。

实际应用

在了解了上述概念后,回到我们的电脑

在windows系统下,我们安装的php大概是这样的,由配置文件和可执行文件组成,可以看到里面有一个我们上文提到的php-cgi,注意到我们的文件夹名字是php nts,这代表Non-Thread Safe(非线程安全)与TS线程安全相对,当然这个概念在这里不重要,不多讨论。

image-20241030152711728

关于nginx或者apache的设置在phpstudy_pro\Extensions\Nginx1.15.11\conf\vhosts或phpstudy_pro\Extensions\Apache2.4.39\conf\vhosts下面

可以看到fastcgi相关部分,但是这个在linux系统下面看的更直接一点

image-20241030154545958

而在linux系统下,fpm里面主要是配置信息,而可执行文件在/usr/bin里面

image-20241030154128399

nginx配置:在\etc\nginx\sites-available可以看到fastcgi_pass unix:/run/php/php7.2-fpm.sock;这是指定的 FastCGI 服务器的地址(php-fpm位置)

server {
		listen 0.0.0.0:80;
		server_name jitamin.test.com;
		root "/var/www/html";

		index index.php;

		charset utf-8;

		location / {
			try_files $uri $uri/ /index.php?$query_string;
		}

		access_log off;
		error_log  /var/log/nginx/jitamin.test.com-error.log error;

		sendfile off;

		client_max_body_size 100m;

		location ~ \.php$ {
			fastcgi_split_path_info ^(.+\.php)(/.+)$;
			fastcgi_pass unix:/run/php/php7.2-fpm.sock;
			#fastcgi_pass 127.0.0.1:9000;
			fastcgi_index index.php;
			include fastcgi_params;
			fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
			fastcgi_intercept_errors off;
			fastcgi_buffer_size 16k;
			fastcgi_buffers 4 16k;
		}

		location ~ /\.ht {
			deny all;
		}
	}

参考文章

https://www.awaimai.com/371.html