nnonkey k1n9的博客

当你为错过太阳而哭泣时,你也要再错过群星了——泰戈尔​

php的运行原理、cgi对比fastcgi以及php-cgi和php-fpm之间的联系区别

前言

为了看这个找了很多文章,这篇文章讲得属实不错,博主地址https://blog.csdn.net/guoke312

了解概念

CGI:
CGI的英文是(COMMON GATEWAY INTERFACE)公共网关接口,它的作用就是帮助服务器与语言通信,这里就是nginx和php进行通信,因为nginx和php的语言不通,因此需要一个沟通转换的过程,而CGI就是这个沟通的协议。

nginx服务器在接受到浏览器传递过来的数据后,如果请求的是静态的页面或者图片等无需动态处理的则会直接根据请求的url找到其位置然后返回给浏览器,这里无需php参与,但是如果是一个动态的页面请求,这个时候nginx就必须与php通信,这个时候就会需要用到cgi协议,将请求数据转换成php能理解的信息,然后php根据这些信息返回的信息也要通过cgi协议转换成nginx可以理解的信息,最后nginx接到这些信息再返回给浏览器。

php-cgi:就是cgi的一个子类吧,为php而生,PHP语言对CGI接口规范的实现也就是PHP-CGI,也就是PHP的解释器。随着技术的发展,PHP-CGI的性能问题逐渐暴露,不是那么尽如人意。PHP在运行的时候是依赖配置文件php.ini的,所以每当PHP-CGI开始工作的时候,它完全是一个新进程,需要重新加载PHP配置文件并初始化,这就造成了很大的资源和时间的浪费。每当客户端请求CGI时,Web服务器就会请求操作系统生成一个新的CGI解释器进程php-cgi.exe,CGI的一个进程处理完一个请求后退出,下一个请求来时在先操作系统申请创建新进程。在访问量较少没有并发的情况下这样做是没有问题的,一旦出现访问量增大,并发出现时这种方式就不再合适了,于是便出现了FastCGI。

fast-cgi:
FastCGI是Web服务器与处理程序之间通信的一种协议,是CGI的改进版本。

传统的cgi协议在每次连接请求时,会开启一个进程进行处理,处理完毕会关闭该进程,因此下次连接,又要再次开启一个进程进行处理,因此有多少个连接就有多少个cgi进程,这也就是为什么传统的cgi会显得缓慢的原因,因此过多的进程会消耗资源和内存。

而fast-cgi则是一个进程可以处理多个请求,和上面的cgi协议完全不一样,cgi是一个进程只能处理一个请求,这样就会导致大量的cgi程序,因此会给服务器带来负担。

php-fpm:php-fpm是php提供给web serve也就是http前端服务器的fastcgi协议接口程序,它不会像php-cgi一样每次连接都会重新开启一个进程,处理完请求又关闭这个进程,而是允许一个进程对多个连接进行处理,而不会立即关闭这个进程,而是会接着处理下一个连接。它可以说是php-cgi的一个管理程序,是对php-cgi的改进。

FastCGI是一个协议,PHP-FPM实现了这个协议。FastCGI是CGI的改进版,它是一个常驻内存的CGI服务。常用的PHP-FPM就是在这种模式下运行的,PHP-FPM负责Fork多个进程,每个进程都运行着PHP解释器。

php-fpm会开启多个php-cgi程序,并且php-fpm常驻内存,每次web serve服务器发送连接过来的时候,php-fpm将连接信息分配给下面其中的一个子程序php-cgi进行处理,处理完毕这个php-cgi并不会关闭,而是继续等待下一个连接,这也是fast-cgi加速的原理,但是由于php-fpm是多进程的,而一个php-cgi基本消耗7-25M内存,因此如果连接过多就会导致内存消耗过大,引发一些问题,例如nginx里的502错误。

2024-01-30T02:33:24.png
下面是图片形式理解
fastcgi
2024-01-30T02:33:59.png
cgi
2024-01-30T02:34:22.png

举个例子

用户访问http://127.0.0.1/index.php?a=1&b=2,如果web目录是/var/www/html,那么Nginx会将这个请求变成如下key-value对:

{ 'GATEWAY_INTERFACE': 'FastCGI/1.0', 'REQUEST_METHOD': 'GET', 'SCRIPT_FILENAME': '/var/www/html/index.php', 'SCRIPT_NAME': '/index.php', 'QUERY_STRING': '?a=1&b=2', 'REQUEST_URI': '/index.php?a=1&b=2', 'DOCUMENT_ROOT': '/var/www/html', 'SERVER_SOFTWARE': 'php/fcgiclient', 'REMOTE_ADDR': '127.0.0.1', 'REMOTE_PORT': '12345', 'SERVER_ADDR': '127.0.0.1', 'SERVER_PORT': '80', 'SERVER_NAME': "localhost", 'SERVER_PROTOCOL': 'HTTP/1.1'}
这个数组其实就是PHP中$_SERVER数组的一部分,也就是PHP里的环境变量。但环境变量的作用不仅是填充$_SERVER数组,也是告诉fpm:“我要执行哪个PHP文件”。

PHP-FPM拿到fastcgi的数据包后,进行解析,得到上述这些环境变量。然后,执行SCRIPT_FILENAME的值指向的PHP文件,也就是/var/www/html/index.php。

总结

因为ningx和php语言不通,如果要进行通信,那么就需要在之间搭一个桥,cgi就是这个桥,是一个协议,可以处理之间的数据,但是因为一次连接就需要启动一个cgi进程,cgi每次都要重新加载php的配置文件,很浪费内存,效率低,出现了fastcgi,phpfpm是它的管理,就是fastcgi是一个工具,而fpm能够更高效率的利用fastcgi,因为fastcgi相当于已经配置好了,是一个通道,只需要数据进行处理,不需要重新加载配置,就会高效。

本原创文章未经允许不得转载 | 当前页面:nnonkey k1n9的博客 » php的运行原理、cgi对比fastcgi以及php-cgi和php-fpm之间的联系区别

评论 1

  1. [...]前言如果需要理解fastcgi攻击,就需要先了解一些基础知识,明白fastcgi到底是什么,参考文章http://49.232.222.195/index.php/archives/193/,当然,根本不够,还需要一些知识,将会在这里讲解,其实也是抄的,内容来自博主https://www.freebuf.com/author/ATL%E5%AE%89%E5%85%A8%E5%9B%A2%E9%98[...]