认识
什么是CGI?CGI是一种用于在Web服务器和外部程序之间通信的标准接口,实际上是一组规范和约定,它允许web服务器调用外部程序来处理客户端的HTTP请求,并将处理结构返回给客户端浏览器。CGI是一种早期的Web服务器编程方式,现在已经不常见。因为CGI是一种标准,类似的,在JAVA中也有使用,用于处理HTTP请求和生成响应,那就是“Java Servlet”。现在已经不常见使用CGI跟Web服务器通信了,从PHP来讲,其中php4.x到现在已经经历过从重瞳CGI向其他方向迁移的历程了,从PHP5.x开始,PHP引入了一种称为SAPI(Server Application Programming Interface)的体系结构,其中包括了不同的处理方式比如CGI、FastCGI(FastCGI是一种改进的CGI方式,它允许长期运行的PHP进程,以便更好地处理多个请求。与传统的CGI不同,FastCGI进程可以保持打开状态,处理多个请求,而不必每次请求都启动和关闭一个新的进程。这提高了性能和效率,同时减少了资源开销。
PHP-FPM就是一种用于管理FastCGI进程的方式,通常与Nginx等Web服务器一起使用)、模块化(PHP模块化方式将PHP解释器作为Web服务器的一个模块嵌入到服务器中,与服务器进程共享内存空间。这使得PHP脚本的执行更加高效,因为不需要每次请求都启动和关闭一个独立的进程。常见的模块化方式包括使用Apache的mod_php或Nginx的php-fpm,它们在Web服务器进程内直接执行PHP脚本。),CLI(命令行界面)和embedded SAPI(嵌入式方式),我们可以根据需要选择不同的SAPI跟Web服务器进行集成。
可以同时使用图同的SAPI吗?一般下,一个web服务器只会使用一种SAPI来与PHP集成,因为每种SAPI都有不同的处理方式和通信机制,他们不会同时运行在同一个web服务器实例上。如果需要使用不同的SAPI,就需要设置不同的虚拟主机或子域,每个虚拟主机可以配置为使用不同的SAPI。再次强调,CGI不仅仅是一个协议,更像是一个标准接口,用于定义Web服务器和外部程序(例如PHP解析器)之间的通信方式,CGI规定了如何格式化HTTP请求,如何将请求传递给外部程序执行以及如何处理外部程序返回的响应数据。
fastcgi的工作方式如下:
- web服务器接受HTTP请求
- 请求被传递到fastcgi进程管理器,比如PHP-FPM
- fastcgi进程管理器选择一个可用的Fastcgi进程来处理请求
- fastcgi进程执行PHP脚本并生成响应
- 响应被传递回web服务器
- web服务器将响应发送回客户端浏览器
虽然fastcgi是一种通用的协议,但每个编程语言和应用程序对他的实现都可能略有不同到这里。拓展一下,这里曾经有个面试题:fastcgi有几种工作模式?fastcgi有两种工作模式,静态进程模型和动态进程模型。为什么要有两种呢?是为了适应不同类型的应用场景和性能需求。首先说说静态进程模型:
- fastcgi进程在web服务器启动时启动,并在web服务器运行期间保持活动状态。
- 每个fastcgi进程可以处理多个请求,因为他们保持长期运行
- 这种模型适用于高并发的情况,因为他减少了频繁启动和关闭进程的开销
- 静态进程模型在高流量的web站点中特别有用,因为它可以更好地利用系统资源,并减少进程启动时间。
然后是动态进程模型:
-
在动态进程模型中,FastCGI 进程是按需启动的,只有在接收到请求时才启动
-
每个 FastCGI 进程通常只处理一个请求,然后在请求处理完成后终止
-
这种模型适用于资源有限的环境,因为它在不活跃时不占用太多资源
-
动态进程模型适用于共享托管环境或资源有限的虚拟主机,因为它可以根据需求动态启动和终止进程,从而减少资源消耗
这两种模式由php-fpm管理配置,默认是使用动态进程模型,也可以自己手动配置。如何配置?看下文“配置php-fastcgi工作模式”。
再补充下FastCGI的工作原理:
- Web Server启动时载入FastCGI进程管理器(IIS ISAPI或Apache Module)
- FastCGI进程管理器自身初始化,启动多个CGI解释器进程(可见多个php-cgi)并等待来自Web Server的连接。
- 当客户端请求到达Web Server时,FastCGI进程管理器选择并连接到一个CGI解释器。Web server将CGI环境变量和标准输入发送到FastCGI子进程php-cgi。
- FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回Web Server。当FastCGI子进程关闭连接时,请求便告处理完成。FastCGI子进程接着等待并处理来自FastCGI进程管理器(运行在Web Server中)的下一个连接。
在CGI模式中,php-cgi在此便退出了。在上述情况中,你可以想象CGI通常有多慢。每一个Web请求PHP都必须重新解析php.ini、重新载入全部扩展并重初始化全部数据结构。使用FastCGI,所有这些都只在进程启动时发生一次。一个额外的 好处是,持续数据库连接(Persistent database connection)可以工作。
php fastcgi通过什么机制实现长期运行Pph进程处理多个请求的呢?
- 进程池管理:PHP FastCGI 使用进程池来管理 PHP 进程。这个进程池包括多个 PHP 进程,每个进程可以处理一个请求。这些 PHP 进程在 Web 服务器启动时启动,并在 Web 服务器运行期间一直保持活动状态
- 请求处理:当 Web 服务器接收到来自客户端的请求时,它会将请求传递给 PHP FastCGI 进程池中的一个可用的 PHP 进程。这个 PHP 进程会处理请求,执行 PHP 脚本,生成响应,并将响应返回给 Web 服务器
- 长期运行:在 FastCGI 模式下,PHP 进程在处理一个请求后通常不会终止。相反,它会保持运行状态,继续等待并处理更多的请求。这使得 PHP 进程能够长期运行,而不需要频繁地启动和关闭
- 进程复用:PHP FastCGI 通过复用进程来处理多个请求。一旦 PHP 进程完成一个请求,它不会立刻终止,而是等待并处理更多请求。这减少了系统资源的消耗,因为启动新进程通常比复用现有进程昂贵
- 请求超时和资源限制:PHP FastCGI 允许为 PHP 进程设置请求超时时间和资源限制。如果请求处理时间超过了指定的超时时间或超出了资源限制,PHP FastCGI 可以终止进程并释放资源,以防止资源泄漏和过度消耗系统资源。 (这里提到进程池、进程复用,这些之后再钻研)
市面上有多种实现了fastcgi功能的进程管理器,php-fpm就是其中的一种。再提一点,php-fpm作为一种fast-cgi进程管理服务,会监听端口,一般默认监听9000端口,并且是监听本机,也就是只接收来自本机的端口请求,所以我们通常输入命令 netstat -nlpt|grep php-fpm 会得到:
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 1057/php-fpm
目前讲了CGI和php fastcgi。下面讲下php-fpm。
对PHP来说,php-fpm是一种实现fastcgi协议的方式,用于管理PHP进程并处理fastcgi请求。fastcgi本身不限定特定的编程语言,它可以与多种语言的应用程序一起使用。php-fpm是PHP的一部分,是PHP解析器的进程管理器。php-fpm可以看做是PHP解析器与fastcgi协议之间的中间层,负责管理php进程,分配请求,执行PHP脚本等。因此,FastCGI 和 PHP-FPM 之间的关系是,PHP-FPM 是 PHP 的一个组件,用于实现 FastCGI 协议,以处理 Web 服务器通过 FastCGI 协议发送的请求。
说到php解析器,他是一个可执行程序,就是安装php后那个php.exe。他可以用来直接执行PHP脚本。PHP-FPM 是 PHP 解析器的一种使用方式,允许 PHP 进程保持长期运行,以提高性能和效率。两者协同工作,使 PHP 成为一种强大的服务器端脚本语言,用于动态生成网页内容。
上面提到了sapi,SAPI全称是Server Application Programming Interface,即服务器应用编程接口,实质上就是定义了一个统一的接口,它的核心就是一个结构体sapi_module_struct。SAPI提供给了外部应用跟php通信的管道,这个外部应用包括不限于Apache,httpd,liunx终端等。 SAPI 不是 PHP 语言本身的一部分,但它是 PHP 运行时环境的关键组成部分。
再来说说zend引擎: Zend 引擎是 PHP 解析器的一部分,它是 PHP 语言的核心组件之一。负责执行语法分析、编译、执行、资源管理、扩展支持。PHP5.6的执行引擎是Zend Engine 2.0,PHP7的执行引擎是Zend Engine 3.0。PHP 7 引入了 Zend Engine 3.0,它在代码执行过程中引入了一些重要的优化。
最后,理解php-fpm后有什么实际意义呢?
- 利用php-fpm做性能优化:首先说说什么时候对php-fpm做性能优化:当应用程序流量增加,请求增加,服务器响应变慢或不稳定时;当应用要处理大量请求比如促销活动时;当服务器的资源(比如内存、cpu、网络宽带)接近极限且性能下降时;当数据库查询变慢时;当频繁的PHP错误或异常时(比如超时、内存不足或进程崩溃)。利用php-fpm做性能优化的关键步骤有:
- 配置php-fpm,调整配置选项(比如进程池大小、进程资源限制、请求超时时间);在Linux系统上,还可以通过命令行工具(如ps、top等)来查看当前运行的php-fpm进程数量和状态,以便监控和调整进程池的配置
- 监控和日志记录:启用 PHP-FPM 的日志记录功能,以便您能够跟踪性能和错误信息。如何开启php-fpm日志功能:找到php-fpm配置文件,修改:error_log:用于定义 PHP-FPM 错误日志的路径 / access.log:用于定义 PHP-FPM 访问日志的路径 / slowlog:用于定义 PHP-FPM 慢查询日志的路径,然后重启
sudo systemctl restart php-fpm - 选择适当的进程管理模型。静态or动态
- 使用缓存:使用 PHP 缓存机制,如 OPCache
- 负载均衡:如果有多个 PHP-FPM 实例,可以使用负载均衡器来均匀分配请求,以避免单个实例的过度负载。(具体怎么负载均衡)
一些实际操作
使用PHP-FPM来控制PHP-CGI的FastCGI进程
/usr/local/php/sbin/php-fpm{start|stop|quit|restart|reload|logrotate}
--start 启动php的fastcgi进程
--stop 强制终止php的fastcgi进程
--quit 平滑终止php的fastcgi进程
--restart 重启php的fastcgi进程
--reload 重新平滑加载php的php.ini
--logrotate 重新启用log文件
配置使用不同sapi
如果在控制台运行脚本,server api的参数会显示:Command Line Interface;如果是配置了cgi运行或者fastcgi运行会在server api那里显示CGI/FastCGI
- 以模块的方式运行,在Apache的配置文件里添加如下配置:
LoadModule php5_module "C:/php5/php5apache2_2.dll" //大约line 127
PHPinidir "C:/php5/php.ini"
//修改配置
DirectoryIndex index.html index.php//追加index.php
AddType application/x-httpd-php .php //line 408左右添加
2. cgi的运行方式,在php.ini修改配置
cgi.force_redirect = 0 //本来是 1 并且去掉注释符号;
修改apache的配置,去掉原来的模块配置
AddType application/x-httpd-php .php
LoadModule php5_module "C:/php5/php5apache2_2.dll"
PHPinidir "C:/php5/php.ini"
加入以下配置
AddHandler cgi-script .cgi // line 396
然后我们在目录C:/Program Files/Apache Software Foundation/Apache2.2/cgi-bin新建一个cgi文件test.cgi编写如下代码:
#!c:/php5/php-cgi.exe
<?
php php phpinfo();
?>
最后我们访问http://localhost/cgi-bin/test.cgi,出现Server API 为 CGI/FastCGI就说明配置成功。
如果同时打开多个则会有很多php-cgi.exe,并且在执行完成之后消失:
- fastcgi的运行方式
PHP的fastcig方式运行,首先需要去下载fastcgi模块,默认是没有带这个模块的,而cgi是自带的;下载地址httpd.apache.org/mod_fcgid/;…
LoadModule fcgid_module modules/mod_fcgid.so // line 128追加
FcgidInitialEnv PHPRC "c:/php5" //php配置文件 line 129追加
AddHandler fcgid-script .php //添加句柄 即后缀 什么样的文件需要fastcgi解释 line 407追加
FcgidWrapper "c:/php5/php-cgi.exe" .php //解释器路径 line 408
Options Indexes FollowSymLinks ExecCGI //line 221 追加 ExecCGI 意思是目录允许执行CGI脚本
出现一下内容说明配置成功: