mod_php和mod_fastcgi和php-fpm的介绍,对比,和性能数据

http://wenku.baidu.com/view/887de969561252d380eb6e92&clickSort=download

对比_mod_php_mod_fastcgiphp-fpm

 

目录

什么是mod_php和mod_fastcgi 1

工作原理 1

mod_php 2

mod_fastcgi 3

mod_factcgi的三种配置方式 4

静态配置 5

动态配置 5

远程方式 6

php-fpm 6

性能测试 8

名称解释 8

测试内容 8

测试结果 8

fastcgi配置项对性能的影响。 11

分析&结论 13

附录 14

apache+mod_fastcgi+php搭建 14

 

什么是mod_php和mod_fastcgi

在lamp体系中,对于apache端php的配置,我们最常用的就是mod_php, 它把PHP做为APACHE一个内置模块。让apache http服务器本身能够支持PHP语言,不需要每一个请求就启动PHP解释器来解释PHP。

和把webserver与php绑定起来的方式不同,fastcgi是HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,相当于一个程序接口。它可以接受来自web服务器的请求,解释输入信息,将处理后的结果返回给服务器(apache,lighty等)。mod_fastcgi就是在apache下支持fastcgi协议的模块。

工作原理

在介绍这两种模式的工作原理前,我们先了解一下php的架构

 

图1 php架构图

上面是php的架构图,从图上可以看到, SAPI提供了一个和外部通信的接口,使得PHP可以和其他应用进行交互数据。php默认提供了很多种SAPI,常见的给apache的mod_php5,CGI,给IIS的ISAPI,还有Shell的CLI。对于一个基于apache的php应用,其运行流程可以简单归结如下

apache -> httpd -> mod_phpfastcgi -> sapi -> php

我们下面提到的两种工作方式就分别用到了mod_php5和cgi的sapi。

 

mod_php

mod_php是在lamp体系中最常使用的工作方式,在这种模式下,php被编译为apache的一个内置模块,在启动时加载。当有一个php请求过来时,直接在httpd进程里完成php的解释运行,将结果返回。

在php的sapi中,有这样一个函数: sapi_cgibin_ub_write, 这个函数告诉了Zend,如何输出数据。查看mod_php的sapi源码,我们会发现,这个函数直接调用了apache的ap_rwrite函数。所以,用mod_php,我们可以把php和apache看做一个模块,两者绑定在一起。其工作原理如下图所示

 

图2 mod_php工作原理

 

mod_fastcgi

在说明fastcgi之前,先了解一下普通cgi的工作流程:

web server收到用户请求,并把请求提交给cgi程序,cgi程序根据请求提交的参数作应处理,然后输出标准的html语句返回给web server,web server再返回给客户端,这就是普通cgi的工作原理。

fastcgi是基于cgi架构的扩展,他的核心思想就是在web server和具体cgi程序之间建立一个智能的可持续的中间层,统管cgi程序的运行,这样web server只需要将请求提交给这个层,这个层再派生出几个可复用的cgi程序实例,然后再把请求分发给这些实例,这些实例是可控的,可持续,可复用的, 因此一方面避免了进程反复fork,另一方面又可以通过中间层的控制和探测机制来监视这些实例的运行情况,根据不同的状况fork或者回收实例,达到灵活 性和稳定性兼得的目的。modFastCGI的主要优点是把动态语言和web server分离开来。这种技术允许把web server和动态语言运行在不同的主机上,以大规模扩展和改进安全性而不损失生产效率。

基于mod_fastcgi方式的php应用,其典型工作流程如下

 

 

图3 mod_fastcgi工作原理

 

从图上可以看出, apache启动后,mod_fastcgi会在启动多个cgi程序,也就是php-cgi脚本。具体脚本的数目通过配置来指定。当有http请求到来后,httpd进程会选择一个当前空闲的一个php-cgi程序来执行,执行的方式和mod_php类似,也是通过php-cgi提供的sapi完成交互。查看源码,可以发现对于cgi的sapi,和mod_php不同,它是把结果输出到fastcgi提供的stdout上,fastcgi再将数据返回给httpd完成交互。

 

 

mod_factcgi的三种配置方式

基于mod_fastcgi的fastcgi应用一共有三种配置方式:静态、动态和远程。他们通过apache配置中的伪指令来代替,对应于三种方式的伪指令分别是FastCgiServer, FastCgiConfig, 以及FastCgiExternalServer。

对于静态和动态这两种方式,apache将通过mod_fastcgi自带的进程管理工具(fcgi-pm)来管理fastcgi应用程序,也就是php-cgi。fcgi-pm在apache启动时就被自动激活了。相对于前两种,远程模式下,php-cgi不由fcgi-pm来管理,apache不会去关心php-cgi程序的状态。

下面详细说一下三种配置方式

静态配置

通过FastCGIServer 伪指令将文件名定义为静态 FastCGI 应用程序。初始时需要指定启动的php-cgi进程数目,默认为1个。apache运行过程中,如果静态应用程序实例因为任何原因死了,那么fcgi-pm将衍生另一个实例来替换。

语法 FastCgiServer file name [options]

 

重要参数说明

idle-timeout n(30 秒)。在请求异常终止和事件记录在 error LogLevel 前,所允许的 FastCGI 应用程序不活动秒数。仅当存在与 FastCGI 应用程序的暂挂连接时,该不活动计时器才应用。如果应用程序在此期间不响应队列的请求,那么请求异常终止。如果与应用程序的通信完成,但是与客户机的通信未完成(缓存的响应),那么超时不应用。

processes n(1)。在服务器初始化时衍生的应用程序实例数。

port n 无。应用程序用于与 Web 服务器通信的 TCP 端口号(1-65535)。此选项使应用程序可以从网络中的其他机器访问。-socket 选项和 -port 选项是互斥的。

socket filename unix sock文件名

Restart-delay n(5 秒)。此应用程序的失败实例重新衍生之间的最小秒数。此延迟阻止中断的应用程序使用过多系统资源。

 

动态配置

在静态配置中,我们初始就指定了要启动的php进程数。和静态的相反,动态应用程序根据需求启动。php应用实例的数目根据当前http请求数目动态变化,进程的管理也是通过fcgi-pm来完成。

语法 FastCgiConfig option [option …]

重要参数说明

和静态方式相比,动态配置的参数主要增加了以下几个

maxProcesses n  在任何时候允许运行的最大动态 FastCGI 应用程序实例数。

minProcesses n 任何时候允许运行,且无须由fcgi-pm(因没有需求)杀死的最小动态 FastCGI 应用程序实例数。

在dyn模式下,因为fastcgi实例数目是动态改变的。所以没有静态方式中process这个参数

 

远程方式

这种模式下,fastcgi实例和apache分离开来,这两者可以分开来部署。他们之间的通信通过tcp或者unix sock来完成。使用ext方式,fastcgi实例将不会由fcgi-pm来管理,而是独立的运行。

语法 – FastCgiExternalServer 文件名 -host 主机名端口 [-appConnTimeout n]

FastCgiExternalServer 文件名 -socket 文件名 [-appConnTimeout n]

重要参数说明

idle-timeout n (30 秒) 在请求异常终止,并且事件记录之前,允许 FastCGI 应用程序保持不活动的秒数。只有当与 FastCGI 应用程序的连接暂挂时,此不活动定时器才适用。如果请求进入应用程序的请求队列,而此应用程序在此期间没有响应(通过写和刷新),则此请求将异常终止。如果与应用程序的通信已完成,而与客户机的通信尚未完成(响应被高速缓存),则此超时不适用。

host host:port 应用程序用于与 Web 服务器通信的主机名或 IP 地址和 TCP 端口号 (1-65535)。-socket 和 -host 选项是互斥的。

socket 文件名 无

应用程序用于与 Web 服务器通信的 UNIX 域套接字的文件名。此文件名相对于 FastCgiIpcDir。-socket 和 -port 选项是互斥的。

 

 

php-fpm

使用FastCGI,最主要优点是把应用和web server(apache)分离开来。这样允许把web server和动态语言(php)运行在不同的主机上,以大规模扩展和改进安全性而不损失效率。

这样的情况下,对于php-cgi程序,由于从apache中分离出来,就需要一个单独的工具来对这些进程进行管理,在stc和dyn两种模式下,mod_fastcgi中自带的fcgi-pm会充当了这样的角色。可是,ext模式下却没有。我们只能通过一个脚本静态的启动n个实例,一旦进程死掉,还需要手工重启。当然,你可以使用supervise来管理这些进程,但是毕竟不那么灵活而且也仅仅一部份问题。甚至于fcgi-pm,因为实现的原因,其本身也有很多问题,例如不太稳定,压力下出core,无法平滑的完成切换等。

基于上述的原因,我们需要一个稳定可靠的进程管理工具,就像lighty下的spwn-cgi。幸运的是,出现了php-fpm。它是一个类似于spwn-cgi的管理工具,可以和任何支持远端FastCGI的web server工作。在官方的手册上,列举了以下php-fpm所具有的特性:

 

特性 Php自带的 Spwn-cgi Php-fpm
php守护程序: pid file, log file, setsid(), setuid(), setgid(), chroot() (-) (-) (+)
进程控制,可以平滑地重启、重新载入配置和二进制模块而不丢失请求 Php4 (-)

Php5 只能平滑停止

(-) (+)
限制ip地址,可以满足web server的要求 php4 (-)

php5.2.2 >  (+)

(-) (+)
如果使用优化器,在遇到opcode缓存随机损坏的时候紧急重启所有进程 (-) (-) (+)
使用用不同的uid / gid / chroot / 环境变量,不同的 php.ini 选项,不需要safe mode (-) (-) (+)
记录work process的stdout和stderr (-) (-) (+)
如果set_time_limit没有起作用,强制结束过期进程 (-) (-) (+)

 

特色功能 Error header、优化的上传支持、fastcgi_finish_request()

另外,php-fpm还可以兼容zend Optimize,各种缓存优化器。

 

 

Php-fpm的安装

Php-fpm是以patch的方式安装的,如果要使用它,你必须在安装php前打上这个补丁。

eg:

gzip -cd php-5.2.6-fpm-0.5.9.diff.gz | patch -d php-5.2.6 -p1

在configure时加上—enable-fpm选项。

 

安装完php后,会有以下几个文件

$prefix/ext/php-fpm.conf

$prefix/log/php-fpm.log

$prefix/log/php-fpm.pid

其中php-fpm.conf是配置文件,具体如何配置文件里有非常详尽的注释。

最后,执行./bin/php-cgi –fpm &就可以了。

另外,你也可以使用$prexif/sbin/php-fpm脚本来方便的维护。

 

 

性能测试

名称解释

ab

apache自测的性能测试工具,主要用于测试极限压力:对于同一url每秒所能执行的次数及响应时间。

 

myab

baidu开发的压力测试工具,区别于ab,其更主要的功能是测试指定压力条件下机器的负载情况。

 

eacc

一种php加速器,主要是将php程序编译后的结果缓存起来。加速php的执行,对性能有很大幅度的提升 ,更详细的情况可以参见另一篇关于php缓存优化的文档 《缓存优化工具-php加速的利器》

 

etc、stc、dyn

mod_fastcgi运行的模式,分别指远程、静态和动态模式

 

 

测试内容

测试中我们将针对不同的运行模式和页面类型进行极限压力测试及机器负载测试。同时,我们还将测试使用缓存优化和不使用缓存优化下机器的表现情况。另外,由于我们的测试主要是对比两种模式的性能差别,因此对于机器的硬件配置不是特别敏感,测试的时候只需要保证机器负载为0即可。

 

 

测试结果

l 最简单的php页面

压力工具:mysql

压力情况:每秒1000次请求,并发数70。

性能指标:cpu idle

 

不同模式下机器idle情况如下图

 

 

图4最简单php页面,1000/s请求 idle情况

 

从图上我们可以看出,测试最简单的php页面时,各种模式下性能几乎没有差别,且由于页面非常简单,eacc的效果也基本没有。

 

 

l 复杂的php程序(2000行代码+)

压力工具:mysql

压力情况:每秒400次请求,并发数70

性能指标:cpu idle

 

测试结果如下图

 

 

图5复杂的php代码,400/s压力idle情况

 

从图上可以看出,在php代码复杂的情况下,前面4中模式性能差别不大,mod_php略优,然后fastcgi动态配置的方式在此情况下性能差距非常之大,idle直接降为0,同时虽然每秒是400次的压力,其只能处理200次左右的请求。

由于php代码很复杂,eacc的作用明显体现出来,使用缓存优化后性能提升一倍以上。

另外,还可以看出,eacc这样的缓存优化工具对于mod_php和fastcgi方式起到的作用基本相同,他们之间的性能差异和使用前维持相同。

在上述情况下,如果不适应fpm,fastcgi模式会出core,主要原因还在在于进程管理的问题。

 

 

l 实际项目中的php程序

这里我们采用群组项目中的pb页面,涉及到和数据库交互,db交互2次。db部署在其他机器,每次请求耗时50ms左右。

 

压力工具:mysql

压力情况:每秒400次请求,并发数70

性能指标:cpu idle

 

测试结果如下

 

 

 

图6实际的php页面,400/s压力idle情况

 

从图上可以看出,性能的情况和图2类似,各种模式的差距仍然不大。

 

l 极限压力测试

 

压力工具:ab

测试参数:并发请求数100,总次数10000次。

测试页面:pb页面

性能指标:每秒请求数 rps

 

 

 

图7极限压力测试 pb页面

 

从上图我们可以看到,极限压力下,使用eacc后,mod_php和ext(fpm)基本差不多,保持在860/s左右的水平,而使用fpm方式进行管理的模式略优于其他两种fastcgi模式。

测试中发现,fastcgi模式下,不使用php-fpm管理的话,仍然会有core出现。

 

fastcgi配置项对性能的影响。

在mod_fastcgi下,不管是ext还是stc方式,有一个配置项是非常关键的:默认启动的php-cgi进程实例数

从fastcgi原理可以看出,当有一个httpd进程到来时,它需要调用fastcgi server来执行,如果此时所有server都出于服务状态,则这个httpd进程将出于等待状态得不到服务,导致请求无法响应。

对pb页面进行测试,配置不同的实例数目进行极限压力测试,得到结果如下

 

 

图8 fastcgi实例数对性能的影响

 

分析一下这个原因:

我们的pb页面执行时间是50ms,也就是说一个php-cgi程序在1s内可以处理的请求数目是1000/50 = 20。假设启动的实例数目是n,则1s内最多能完成的请求数为n*20,从图上可以看出,实际结果符合我们的计算。另外,这个数值也不是无限增大了,当n*20大于server本身所能承受的极限时,rps也不会继续往上增长了。

所以,使用fastcgi,对于n的选择,要综合页面平均处理时间,最大压力等多种因素结合来配置。

 

 

同时,在ext方式下,webserver和fastcgi server交互的方式有两种:通过tcp或者unix sock。测试一下这两种方式的情况

使用myab每秒400次请求pb页面,机器idle

 

 

图9 ext下unix sock和tcp的区别

 

从图上可以看出,不管是否使用eacc,tcp方式的idle都有一个百分点的下降,这个差异主要是因为多了tcp连接过程造成的。

 

分析&结论

根据各种测试结果,可以看出和fastcgi方式相比,mod_php的性能在各种情况下都稍优,这种差异主要是在于后一种方式增加了一次数据交互过程php->fascgi->apache。但是这个差距并不大,在使用了eacc等缓存优化工具后,性能有了很大提升。他们之间的差距完全不是瓶颈。从使用的角度来说,fastcgi具有以下优点:

1. webserver和php程序分离,两者可以部署在不同的地方,通过socket方式通信带来一定安全性

2. 使用fastcgi,在出现问题时可以更好的定位是webserver还是php的原因

3. fastcgi方式不依赖于webserver,更加灵活,扩展性也更好

4. fastcgi本身会有一些进程监控和日志记录,更便于分析问题,跟踪状态。

5. 灵活多样的配置,可以根据实际的应用进行合理配置达到最佳效果。

 

当然fastcgi也有一些缺点

1. mod_fastcgi在进程管理上有一些问题,容易出core。这个问题通过使用php-fpm可以解决

2. 由于fastcgi应用单独分离出来,因此需要单独监控进程的状态。防止进程挂掉后导致服务出现问题,这个可以通过使用用supervise管理一定程度上避免这个问题。

3. 文档相对缺乏,mod_fastcgi对apache的支持也不是特别好,且基本没有升级。

 

关于fastcgi运行方式的选择,从效率、稳定性等各方面来说,ext方式是最佳选择了。而且考虑到我们可能会将webserver和php分开到不同机器,选择远程方式也是必须的。

进程管理工具,从各方面来说,php-fpm是最优选择了,即时使用lighty作用web server,也完全可以用它代替spwn-cgi。

 

综合测试结果和上述分析,我们完全可以采用fastcgi代替传统的mod_php。推荐使用下面的组合方式

apache + ext + php-fpm(with superwise)

如果webserver和fastcgi部署在同一机器上,使用unix sock方式通信,否则使用tcp方式。

 

 

 

 

 

附录

apache+mod_fastcgi+php搭建

l php

mod_fastcgi的搭建主要有三种方式

stc、ext和dyn,不管是哪种方式,首先在安装php的时候需要加上如下选项

–enable-fastcgi,并且不能使用—with-apxs。

以下是一个配置php例子

 

./configure \

–prefix=/home/club/hongdk/env/php5.26-fcgi/ \

–enable-trace-vars \

–with-zlib-dir=/home/club/hongdk/tool/zlib/ \

–with-mysql=/home/club/hongdk/env/mysql5/ \

–with-mysqli=/home/club/hongdk/env/mysql5/bin/mysql_config \

–with-gettext \

–with-iconv \

–enable-mbstring=gbk \

–with-xmlrpc \

–enable-safe-mode \

–enable-sockets \

–enable-url-fopen-wrapper \

–enable-ftp \

–enable-shmop \

–with-config-file-path=/home/club/hongdk/env/php5.26-fcgi/ \

–enable-xml \

–with-dom=/home/club/hongdk/tool/libxml/ \

–with-libxml-dir=/home/club/hongdk/tool/libxml/ \

–with-curl=/home/club/hongdk/tool/curl \

–with-curlwrappers \

–enable-fastcgi \

 

在安装完后,会在php的bin目录下找到如下文件php-cgi

执行 ./php-cgi –v,如果看到

PHP 5.2.5 (cgi-fcgi) (built: Nov 12 2008 20:44:08)

Copyright (c) 1997-2007 The PHP Group

Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies

就表明安装成功了

 

l mod_fastcgi

cd mod_fastcgi-2.4.6

cp Makefile.AP2 Makefile

vi Makefile

修改top_dir为apache安装目录

make

make install

 

 

l apache配置

修改httpd.conf

首先增加

LoadModule fastcgi_module modules/mod_fastcgi.so

 

然后根据不同的运行模式进行配置

eg

ext模式

<IfModule mod_fastcgi.c>

FastCgiExternalServer $php-server -socket /home/club/fastcgi.sock

ScriptAlias /cgi-bin/ “/home/club/hongdk/env/apache-fcgi/cgi-bin/”

AddHandler php-fastcgi .php

Action php-fastcgi /cgi-bin/php-cgi

AddType application/x-httpd-php .php

</IfModule>

 

其中$php-sever为php-cgi程序,例如/home/club/hongdk/env/apache-fcgi/cgi-bin/php-cgi

 

stc模式

<IfModule mod_fastcgi.c>

FastCgiServer $php-server -processes 10

ScriptAlias /cgi-bin/ “/home/club/hongdk/env/apache-fcgi/cgi-bin/”

AddHandler php-fastcgi .php

Action php-fastcgi /cgi-bin/php-cgi

AddType application/x-httpd-php .php

</IfModule>

 

dyn模式

<IfModule mod_fastcgi.c>

FastcgiConfig –idle-timeout 120

ScriptAlias /cgi-bin/ “/home/club/hongdk/env/apache-fcgi/cgi-bin/”

AddHandler php-fastcgi .php

Action php-fastcgi /cgi-bin/php-cgi

AddType application/x-httpd-php .php

</IfModule>

 

然后,定义fastcgi server也就是我们的php-cgi程序所在文件夹的权限

<Directory $php-server>

Options ExecCGI

Order allow,deny

Allow from all

</Directory>

 

 

l fastcgi应用

在我们的应用中就是php-cgi

如果是stc和dyn方式,不需要单独再启动php-cgi,他们的管理有mod_fastcgi自带的fcgi-pm来完成

在etc模式下,我们需要单独启动php-cgi程序

可以用php-fpm来完成。也可以独立的使用一个脚本来启动,例如

 

#!/bin/sh

exec &> /dev/null

exec < /dev/null

PHP_FCGI_CHILDREN=32

export PHP_FCGI_CHILDREN

exec /home/club/hongdk/env/apache-fcgi/cgi-bin/php-cgi -b ./xl.sock -c /home/club/hongdk/env/php5-fcgi/php.ini

 

推荐使用php-fpm来完成

搞不清FastCgi与PHP-fpm之间是个什么样的关系

 

http://segmentfault.com/q/1010000000256516

 

我在网上查fastcgi与php-fpm的关系,查了快一周了,基本看了个遍,真是众说纷纭,没一个权威性的定义。

网上有的说,fastcgi是一个协议,php-fpm实现了这个协议; 有的说,php-fpm是fastcgi进程的管理器,用来管理fastcgi进程的; 有的说,php-fpm是php内核的一个补丁; 有的说,修改了php.ini配置文件后,没办法平滑重启,所以就诞生了php-fpm; 还有的说PHP-CGI是PHP自带的FastCGI管理器,那这样的话干吗又弄个php-fpm出来,我就更晕了;

发个贴,想听听大家的理解,网上的我都已经看了个遍,因为我查了一周了,哈哈,所以想听听原创的理解。

在低诉152

7月21日提问

6 个回答

9赞

采纳

刚开始对这个问题我也挺纠结的,看了《HTTP权威指南》后,感觉清晰了不少。

首先,CGI是干嘛的?CGI是为了保证web server传递过来的数据是标准格式的,方便CGI程序的编写者。

web server(比如说nginx)只是内容的分发者。比如,如果请求/index.html,那么web server会去文件系统中找到这个文件,发送给浏览器,这里分发的是静态数据。好了,如果现在请求的是/index.php,根据配置文件,nginx知道这个不是静态文件,需要去找PHP解析器来处理,那么他会把这个请求简单处理后交给PHP解析器。Nginx会传哪些数据给PHP解析器呢?url要有吧,查询字符串也得有吧,POST数据也要有,HTTP header不能少吧,好的,CGI就是规定要传哪些数据、以什么样的格式传递给后方处理这个请求的协议。仔细想想,你在PHP代码中使用的用户从哪里来的。

当web server收到/index.php这个请求后,会启动对应的CGI程序,这里就是PHP的解析器。接下来PHP解析器会解析php.ini文件,初始化执行环境,然后处理请求,再以规定CGI规定的格式返回处理后的结果,退出进程。web server再把结果返回给浏览器。

好了,CGI是个协议,跟进程什么的没关系。那fastcgi又是什么呢?Fastcgi是用来提高CGI程序性能的。

提高性能,那么CGI程序的性能问题在哪呢?”PHP解析器会解析php.ini文件,初始化执行环境”,就是这里了。标准的CGI对每个请求都会执行这些步骤(不闲累啊!启动进程很累的说!),所以处理每个时间的时间会比较长。这明显不合理嘛!那么Fastcgi是怎么做的呢?首先,Fastcgi会先启一个master,解析配置文件,初始化执行环境,然后再启动多个worker。当请求过来时,master会传递给一个worker,然后立即可以接受下一个请求。这样就避免了重复的劳动,效率自然是高。而且当worker不够用时,master可以根据配置预先启动几个worker等着;当然空闲worker太多时,也会停掉一些,这样就提高了性能,也节约了资源。这就是fastcgi的对进程的管理。

那PHP-FPM又是什么呢?是一个实现了Fastcgi的程序,被PHP官方收了。

大家都知道,PHP的解释器是php-cgi。php-cgi只是个CGI程序,他自己本身只能解析请求,返回结果,不会进程管理(皇上,臣妾真的做不到啊!)所以就出现了一些能够调度php-cgi进程的程序,比如说由lighthttpd分离出来的spawn-fcgi。好了PHP-FPM也是这么个东东,在长时间的发展后,逐渐得到了大家的认可(要知道,前几年大家可是抱怨PHP-FPM稳定性太差的),也越来越流行。

好了,最后来回来你的问题。
网上有的说,fastcgi是一个协议,php-fpm实现了这个协议

对。

有的说,php-fpm是fastcgi进程的管理器,用来管理fastcgi进程的

对。php-fpm的管理对象是php-cgi。但不能说php-fpm是fastcgi进程的管理器,因为前面说了fastcgi是个协议,似乎没有这么个进程存在,就算存在php-fpm也管理不了他(至少目前是)。 有的说,php-fpm是php内核的一个补丁

以前是对的。因为最开始的时候php-fpm没有包含在PHP内核里面,要使用这个功能,需要找到与源码版本相同的php-fpm对内核打补丁,然后再编译。后来PHP内核集成了PHP-FPM之后就方便多了,使用--enalbe-fpm这个编译参数即可。

有的说,修改了php.ini配置文件后,没办法平滑重启,所以就诞生了php-fpm

是的,修改php.ini之后,php-cgi进程的确是没办法平滑重启的。php-fpm对此的处理机制是新的worker用新的配置,已经存在的worker处理完手上的活就可以歇着了,通过这种机制来平滑过度。

还有的说PHP-CGI是PHP自带的FastCGI管理器,那这样的话干吗又弄个php-fpm出

不对。php-cgi只是解释PHP脚本的程序而已。

尹川160

7月30日回答

  • 1
    尹川 · 7月30日回复依云:
    呵呵,多谢你的赞。在segmentfault的第一个‘踩’和‘赞’都是你给的,哈哈。

  • 更多评论 (5条)

你(PHP)去和爱斯基摩人(web服务器,如 Apache、Nginx)谈生意

你说中文(PHP代码),他说爱斯基摩语(C代码),互相听不懂,怎么办?那就都把各自说的话转换成英语(FastCGI 协议)吧。

怎么转换呢?你就要使用一个翻译机(PHP-FPM)
(当然对方也有一个翻译机,那个是他自带的)

我们这个翻译机是最新型的,老式的那个(PHP-CGI)被淘汰了。不过它(PHP-FPM)只有年轻人(Linux系统)会用,老头子们(Windows系统)不会摆弄它,只好继续用老式的那个。

我看了上面三位的答案,但我总觉得他们描述得还不够贴切。

Fastcgi是CGI的升级版,一种语言无关的协议,用来沟通程序(如PHP, Python, Java)和Web服务器(Apache2, Nginx), 理论上任何语言编写的程序都可以通过Fastcgi来提供Web服务。
Fastcgi的特点是会在一个进程中依次完成多个请求,以达到提高效率的目的,大多数Fastcgi实现都会维护一个进程池。

而PHP-fpm就是针对于PHP的,Fastcgi的一种实现,他负责管理一个进程池,来处理来自Web服务器的请求。目前,PHP-fpm是内置于PHP的。

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

fastcgi是一个协议,没错。php-fpm实现了这个协议,没错。 php-fpm的fastcgi协议需要有个金城吧?php-fpm实现的fastcgi进程就叫php-cgi= =。所以php-fpm就是他自身的fastcgi或php-cgi进程管理器,没错。php-fpm在5.2之前官方是没有php-fpm的。php-fpm是作为一个第三方的补丁你才能用的。5.2之后捏,官方就已经默认加入了,从此就不是一个补丁了。

======update:

参考资料:http://baike.baidu.com/view/4168033.htm
使用PHP-FPM来控制PHP-CGI的FastCGI进程
在没有PHP-FPM之前。是直接打开php-cgi.exe(win32)、php-cgi进程来处理fastcgi的请求的。或者是用spawn-fcgi或uwsgi类似的fastcgi进程管理软件。
php-fpm的目的就是解决spawn-fcgi和uwsgi等类似管理器的缺陷并且集成入PHP官方。

另外纠正:php-fpm是自php5.3以后版本才开始被官方加入的

7月21日更新

cevin907

7月21日回答

一篇文章 找出 最长单词 和第二多单词 的话题

15:40:11
这2个是不是算一个问题
15:40:35
你说的hash
15:40:42
是怎么处理的
15:40:58
hash 能计数吗
15:41:20
不一样,最长单词,统计的是单词长度,第二多单词,是词频统计
15:41:35

15:41:38
hash不是用来计数的,是用来存储关键词的
15:42:04
你要给某个关键词计数,你得先找到这个关键词才行
15:42:27
如果你用php
$words[‘单词’]++; 这样就可以了
15:42:59
就是一个循环?
15:43:44
但是你要知道 $words[‘单词’] 这里做了两个操作的

首先是从hash表查找’单词’这个key, 然后再对这个key对应的hash值做++运算
15:43:56
只是php封装了算法而已
15:44:57
这里就是一个计算
15:45:02
没有封装什么吧
15:45:21
你是指数组的操作
15:45:25
是封装了吗
15:45:35
php数组就是hash表
15:45:37
数组是一种数据类型
15:45:38
呵呵
15:45:41

15:46:09
php的数组跟其他语言,比如c语言的数组是不同的
15:46:26

15:47:12
如果用php实现统计最长单词, 只要把单词拿出来,顺便跟上一个最长单词比较下长度就行了
15:47:36

15:47:45
第一次的时候,上一个最长单词就是空的,长度0, 如果比他长,就替换掉
15:47:58
这个知道
15:48:02
扫描一遍文章就ok了
15:48:08

15:48:37
第二多单词的话,要做词频统计
15:48:46
因为不知道,那个单词出现过多少次
15:49:06

15:49:15
那php就是用数组操作
15:49:17
就可以了
15:49:21
词频统计就这样
$words[‘单词’]++;
15:49:23
没有什么特别的技巧吧
15:49:31
这个知道
15:50:18
因为要取第二多单词,所以就需要排序
15:50:33
如果统计完了,在排序,就慢一些
15:50:49
可以一遍统计词数,一遍做排序
15:51:00

15:51:18
这个怎么处理
15:53:03
我在想一个问题,如果一篇文章的单词(不重复)不多的话,没有必要这么啰嗦
15:53:16
直接统计完,php数组排序一下就好
15:53:35
php数组排序函数也是一个算法
15:53:35
这本身就已经很给力了
15:54:04
因为php数组本身用来做统计关键词就已经效率很高了
15:54:20

15:54:27
面试题是问原理
15:54:33
知不知道这样
15:54:39
要不几个函数搞定了
15:54:51
面试官好像很没面子
15:54:56
原理你就说这些函数的算法
15:55:04

15:55:05
php数组的原理
15:55:14
应该也就那样了
15:55:15
还有排序函数的算法原理
15:55:40
确实这些算法,如果自己实现,要写很多代码的
15:55:42
呵呵
15:55:52
是的
15:56:04
你用C语言实现就知道了,非常麻烦
15:56:15

15:56:44
光是实现hash表,估计也要几十行代码
15:56:59

15:57:26
如果hash表要实现完善一些,就更啰嗦了
15:57:48
原理的你就搞清楚下, php数组的原理,其实就是hash表
15:58:01
我之前看过php的部分代码
15:58:55
我后面写的C语言的hash函数,还是用php的内部实现,直接抄过来用了
16:01:01

16:01:13
代码有吗,给我看下
16:01:32
估计以前你没看过hash算法,你可以先了解下hash算法,就是怎么存储key, value数据结构的算法
16:01:46

16:01:55
我看了几次都好像搞不太清楚
16:03:00
简单的说就是通过一个hash函数,计算key的hash值(数值),然后通过这个数值来定位key的存储地址
16:03:16

16:03:17
明白了
16:04:00
那不是 key相同
16:04:06
地址都一直相同了
16:04:12
对呀
16:04:19
地址跟key的对应关系是不变的
16:04:22
否则,你存进去的数据就读不出来了
16:04:26
肯定要相同
16:04:29
地址指向的内容可以变
16:04:33

16:04:35

16:04:46
就是其他程序写进去的key
16:04:49
一样可以用了
16:04:54
地址指向的内容可以变,但是key算出来的地址要一样才行
16:05:16
key对整个内存都是通用的吗
16:05:26
还是java的跟php不能通用
16:06:00
这个跟语言没关系,同样的hash算法,任何语言计算的结果都一样
16:06:09

16:06:13
只是计算是吧
16:06:18

16:06:20
那跟内存的关系有没有
16:06:33
至于能不能访问数据,这个要在自己的程序作用域内
16:06:34
存储不一定是内存
16:06:57
程序计算的时候就是在内存
16:07:04
当然,你可以存储到磁盘上
16:07:09

16:07:35
数据在内存中,作用域不同

每个程序有自己独立的运行空间的
16:07:54
是不是就是内存里存的东西都是一个包这样分割的
16:08:00

16:08:08
我想应该也是,虚拟机
16:08:14
自己划分一块内存是吧
16:08:15
你无法直接访问别的程序的内存数据
16:08:25
那可以有重复的key了
16:08:30

16:08:30
比如32位的系统,每个程序都有4G的空间
16:08:33
虚拟的
16:08:47
确定是这样吗
16:08:54
不是能识别4G吧
16:09:14
这个是操作系统原理的东西
16:09:53

16:10:05
同一个hash表里面,key是唯一的,值就不一定了
16:10:15

16:10:17
看自己的设计要求了
16:10:29
现在终于明白了
16:10:52
至于hash表的数据是不是共享的,也看你自己的需要,你想要他共享,就共享,不希望就是自己用
16:10:59
内存的地址应该就是指针吧,是不是可以随意定义的,还是固定长度的
16:11:02
他就是个存储算法
16:11:08

16:11:24
hash函数算出来的地址,不是内存物理地址
16:11:37
是自己hash表的映射地址,逻辑地址
16:11:38

16:12:02
那这个地址在找到指针吗
16:12:51
这个逻辑地址,肯定能找到指针地址的
16:13:11

16:13:40
比如数组 a[0,1,2,3,4,5]

里面有6个数据 p是指向数组a首地址的指针
16:14:08
因为都是int类型4个字节 p + 4就是第二个元素
16:14:27

16:14:32
当然不一定要操作指针,直接用数组操作也可以a[1]不就行了
16:14:44

16:15:27
hash表的地址映射一般都是用数组保存的
16:15:41
每个数组的下标就是hash值
16:15:51

16:15:59
所以只要通过hash函数,计算key的hash值,就跟数组的下标对上了
16:16:26
a[hash(‘key’)] 伪代码就是这样的意思
16:16:50
我们平时用的数组的key 实际上就是 hash(‘key’) 的值了
16:16:55
这里的数组不是php数字,是底层c数组
16:17:04

16:17:38
平时你php语法,$a[“key”] 实际上就是a[hash(“key”)] 类似这样
16:17:52
c数组的下标 那不是一个很长的hash值
16:17:53
当然还有hash冲突处理
16:18:03
一个数值
16:18:10

16:18:28
如果是64位系统long类型 8个字节
16:18:54
可以存储很大数值,当然为了避免越界,一般都会取模运算
16:19:11

16:19:25
这些你都有研究啊
16:19:40
是不是基本上常用的你都懂啊
16:19:43
就因为存储越界问题,所以有可能会出现hash值冲突
16:19:56

16:20:11
所以有两种常用的算法解决:线性探测法,和链表法
16:20:19
这些算法高中我就学会了
16:20:28

16:20:35
现在都还记得?
16:21:10
原理肯定记得,现在又没脱离写代码
16:21:27
我虽然之前也搞懂了几个算法
16:21:31
现在一个都不记得了
16:21:52
写复杂点的程序也会用到
16:22:04
是的
16:22:07
数据处理,算法很重要,要不性能就很低
16:22:26

16:22:33
即使有现成的算法库,如果不了解原理也用不到,因为没法做比较
16:22:48
如果不了解原理也用不好
16:22:56

16:23:29
常用的算法还是要懂的
16:23:37
而非做性能优化就困难了
16:23:42

16:23:44
否则做性能优化就困难了
16:23:46
我得研究一下
16:24:37
呵呵,编程,知识很多的。
16:24:51
都是要慢慢积累,时间长了懂的就多了
16:25:08

16:25:41
操作系统原理,网络通信协议这些知识少不了,搞大型系统架构,都是在这些基础上构建
16:26:14

16:26:38
大型系统,都经常要压榨计算机的性能
16:27:06

16:27:21
这些觉得离普通项目很远
16:27:39
因为不压榨,成本会越来越高
16:27:56
比如上次新浪微薄的一个阅读数的需求
16:27:59

16:30:13
就是每条微薄的统计下阅读数,如果正常处理,一台处理1万/秒的计算,那么新浪微薄要求的是每秒100万的处理,就需要100台机器,考虑容灾,数据存储安全,那么机器需要200台
16:30:54
是很多
16:30:57
如果每台机器性能优化到一天5万每秒的处理,那么机器成本就要狂降
16:31:10
如果在优化,成本效果显著
16:31:19

16:31:32
大系统一般都比较极端的
16:31:51
小小的一个需求,可能要投入的成本很高的
16:31:51
是的
16:32:22
memcached常用的,实际上内存也很昂贵
16:32:50
是的
16:33:27
比如之前我们的社区,经常稍微加一个key, 那就意味则要新增几千万的memcached 字段存储
16:33:58
数据乱用memcached,内存肯定不够用的