天天看点

PHP 之 FastCGI 与 mod_php 详解

网上对于fastcgi与mod_php的知识比较杂乱而不全面,故在此整理一下,以便入门学习者查阅方便。

<a target="_blank"></a>

php最常用的方式是以模块的方式(mod_php)运行在apache中,也是apache运行php的默认方式;但在nginx中,nginx又使用的是php-fpm,但是php-fpm到底是个什么东东?跟php有什么关系?今天我们一起来探究一番。

首先需要记住的是,任何一种web服务器(apache、nginx等)都是被设计成向用户发送html、图片等静态资源的,web服务器自身并不能解释任何动态脚本(php、python等)。

php处理器就是用来解释web应用中的php代码,并将它解释为html或其他静态资源,然后将解析的结果传给web服务器,最后再由web服务器发送给用户。

大多数的web服务器都不能解析php代码,因此它需要一个能解析php代码的程序,这就是php处理器。

现在我们知道了,apache与nginx都需要php处理器来处理php代码,那么怎么连接上服务器与php处理器呢?也就是说服务器与php处理器如何通信?

答案是通过sapi(server application programming interface 服务器端应用编程端口),简单来说,sapi指的是php具体应用的编程接口, 就像pc一样,无论安装哪些操作系统,只要满足了pc的接口规范都可以在pc上正常运行, php脚本要执行有很多种方式,通过web服务器,或者直接在命令行下,也可以嵌入在其他程序中,有兴趣大家可以研究php内核。

我们这里继续讨论php最常用的sapi提供的2种连接方法:mod_php和mod_fastcgi。

咱们回顾一下,apache是怎么能够识别php代码的?是不是apache的配置文件httpd.conf中加上或者修改这样几句:

<code>//添加</code>

<code>loadmodule php5_module modules/libphp5.so</code>

<code>addtype application/x-httpd-php .php</code>

<code>//修改</code>

<code>&lt;ifmodule dir_module&gt;</code>

<code>directoryindex index.php index.html index.htm index.html</code>

<code>&lt;/ifmodule&gt;</code>

也即php作为apache的一个子模块来运行,当通过web访问php文件时,apache就会调用php5_module来解析php代码。

配置加载mod_php模块后,php便是apahce进程本身一部分,每个新的apache子进程都会加载此模块。

我们先看php-fpm官网的说明:

php-fpm - a simple and robust fastcgi process manager for php php-fpm (fastcgi process manager) is an alternative php fastcgi implementation with some additional features useful for sites of any size, especially busier sites.

php-fpm是一个php的fastcgi进程管理器,解释的非常简单。这说明php-fpm是辅助mod_fastcgi模式进行工作的,然而fastcgi又是个什么东西?管理着什么进程?

cgi(common gateway interface) 是www技术中最重要的技术之一,有着不可替代的重要地位。

cgi是外部应用程序(cgi程序)与web服务器之间的接口标准,是在cgi程序和web服务器之间传递信息的规程。

cgi规范允许web服务器执行外部程序,并将它们的输出发送给web浏览器,cgi将web的一组简单的静态超媒体文档变成一个完整的新的交互式媒体。

说白了,cgi是一种外部应用程序(cgi程序)与web服务器的协议,cgi是为了保证server传递过来的数据是标准格式。

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

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

一般情况下,fastcgi的整个工作流程是这样的:

web server启动时载入fastcgi进程管理器(iis isapi或apache module)。

fastcgi进程管理器自身初始化,启动多个cgi解释器进程(可见多个php-cgi)并等待webserver的连接。

当客户端请求到达web server时,fastcgi进程管理器选择并连接到一个cgi解释器。 web server将cgi环境变量和标准输入发送到fastcgi子进程php-cgi。

fastcgi子进程完成处理后将标准输出和错误信息从同一连接返回web server。当fastcgi子进程关闭连接时,请求便告处理完成,fastcgi子进程接着等待并处理来自fastcgi进程管理器(运行在web server中)的下一个连接,在cgi模式中,php-cgi在此便已经退出。

也就是说fastcgi是cgi的升级版,一种语言无关的协议,用来沟通程序(如php, python, java)和web服务器(apache2, nginx), 理论上任何语言编写的程序都可以通过fastcgi来提供web服务。

fastcgi的特点是会在一个进程中依次完成多个请求,以达到提高效率的目的,大多数fastcgi实现都会维护一个进程池。

通俗解释:fastcgi事先就需要启动,而且可以启动多个cgi模块,在那里一直运行等着web发请求,然后再给php解析运算,完成后生成html返回给web后,但是完成后它不会退出,而是继续等着下一个web请求。

php-fpm就是针对于php的fastcgi的一种实现,他负责管理一个进程池,来处理来自web服务器的请求。

但是php-fpm仅仅是个“php fastcgi 进程管理器”, 它仍会调用php解释器本身来处理请求,php解释器(在windows下)就是php-cgi.exe。

说了这么多,也不知道是否表达清楚,如果有不正确的地方请指正,谢谢。

本文来自云栖社区合作伙伴“linux中国”,原文发布日期:2015-10-12