CGI、FastCGI、PHP-CGI、PHP-FPM、Spawn-FCGI?

PHP运行目前为止主要有三种方式:

  1. 以模块加载的方式运行——将PHP集成到Apache服务器,以同一个进程运行。
  2. 以CGI的方式运行——Apache在遇到PHP脚本的时候会将PHP程序提交给CGI应用程序(php-cgi.exe)解释,解释之后的结果返回给Apache,最后再返回给相应的请求用户。
  3. 以FastCGI的方式运行——CGI的加强版本,CGI是单进程,多线程的运行方式,程序执行完成之后就会销毁,所以每次都需要加载配置和环境变量fork-and-execute(创建-执行)。而FastCGI则不同,FastCGI像是一个常驻 (long-live) 型的CGI,只要激活后,在web服务器启动时就开启了一个进程,它可以一直执行着,不会每次都要花费时间去fork一个进程(CGI最为人诟病的fork-and-execute模式)。

CGI
CGI(Common Gateway Interface)公共网关接口是HTTP服务器与机器上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上。CGI可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量。如php,perl,python,tcl等
工作原理:CGI程序根据请求提交的参数作相应处理,然后输出标准的html语句返回给web server,web server再返回给客户端。

Web Server(比如说httpd)只是内容的分发者。比如请求/index.html,那么Web Server会去文件系统中找到这个文件,发送给浏览器,这里分发的是静态数据。如果现在请求的是/index.php,根据配置文件,httpd知道这个不是静态文件,会启动对应的CGI程序,这里就是PHP的解析器,接下来httpd会把这个请求简单处理后交给PHP解析器,请求处理完成后再以CGI规定的格式返回处理后的结果,退出进程。Web Server再把结果返回给浏览器。

httpd会传哪些数据给PHP解析器呢?
url,查询字符串,POST数据,HTTP header……
CGI就是规定要传哪些数据、以什么样的格式传递给后方处理这个请求的协议,并保证了web server传递过来数据的标准格式。

从上面看,CGI所要实现的就是动态网页,这种处理方式的特点就是每接到一个请求,web server都要fork出一个单独的cgi程序的进程来处理,好处是把web server和具体的程序处理独立开来,结构清晰,可控性强,但是如果在高访问需求的情况下,CGI的进程fork就会成为服务器的很大负担,想象一下数百个并发请求导致服务器fork出数百个进程就会明白为什么CGI一直背负性能低下,高资源消耗的恶名。
FastCGI
FastCGI的核心思想就是在web server和具体CGI程序之间建立一个智能的可持续的中间层,统管CGI程序的运行,这样web server只需要将请求提交给这个层,这个层再派生出几个可复用的CGI程序实例,然后再把请求分发给这些可控的,可持续,可复用的实例, 因此一方面避免了进程反复fork,另一方面又可以通过中间层的控制和探测机制来监视这些实例的运行情况,根据不同的状况fork或者回收实例,达到灵活性和稳定性兼得的目的。
FastCGI是可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中并因此获得较高的性能。众所周知,CGI解释器的反复加载是CGI性能低下的主要原因,如果CGI解释器保持在内存中并接受FastCGI进程管理器调度,则可以提供良好的性能、伸缩性、Fail- Over特性等等。
FastCGI的工作原理

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

举个例子: 服务端现在有个10万个字单词, 客户每次会发来一个字符串,问以这个字符串为前缀的单词有多少个。 那么可以写一个程序,这个程序会建一棵tree树,然后每次用户请求过来时可以直接到这个tree去查找。 但是如果以CGI的方式的话,这次请求结束后这课tree也就没了,等下次再启动该进程时,又要新建一棵trie树,这样的效率就太低下了。 而用FastCGI的方式的话,这课tree树在进程启动时建立,以后就可以直接在tree树上查询指定的前缀了。
在上述情况中,可以想象CGI通常有多慢。每一个Web请求PHP都必须重新解析php.ini、重新载入全部扩展并重初始化全部数据结构。使用FastCGI,所有这些都只在进程启动时发生一次。一个额外的好处是,持续数据库连接(Persistent database connection)可以工作。
FastCGI与CGI特点

  1. 如CGI,FastCGI也具有语言无关性.
  2. 如CGI, FastCGI在进程中的应用程序,独立于核心web服务器运行,提供了一个比API更安全的环境。(APIs把应用程序的代码与核心的web服务器链接在一起,这意味着在一个错误的API的应用程序可能会损坏其他应用程序或核心服务器;恶意的API的应用程序代码甚至可以窃取另一个应用程序或核心服务器的密钥。)
  3. FastCGI技术目前支持语言有:C/C++、Java、Perl、Tcl、Python、SmallTalk、Ruby等。相关模块在Apache,ISS, Lighttpd等流行的服务器上也是可用的。
  4. 如CGI,FastCGI的不依赖于任何Web服务器的内部架构,因此即使服务器技术的变化, FastCGI依然稳定不变。
    这里写图片描述

fastCGI程序与CGI程序与服务器的交互方式也不同,CGI程序通过环境变量、命令行、标准输入输出进行交互,因此CGI程序进程必须与服务器进程在同一台物理计算机上,而fastCGI程序与服务器进程通过网络连接交互,因此FastCGI支持分布式的运算, 即 FastCGI 程序可以在网站服务器以外的主机上执行并且接受来自其它网站服务器来的请求。这不但可以提高性能,同时也提高了系统的扩展能力。
还有一种更高级的方式是web服务器可以内置perl解释器或php解释器。 也就是说这些解释器做成模块的方式,web服务器会在启动的时候就启动这些解释器。 当有新的动态请求进来时,web服务器就是自己解析这些perl或php脚本,省得重新fork一个进程,效率提高了。
小结:
CGI: 需要开启若干个进程;
FastCGI : 需要额外开启一个进程;
PHP_MOD :无需开启额外进程,因为PHP解析器已集成到web服务器中,跟web服务器在同一个进程;
FastCGI的不足
因为是多进程,所以比CGI多线程消耗更多的服务器内存,PHP-CGI解释器每进程消耗7至25兆内存,将这个数字乘以50或100就是很大的内存数。 
PHP-CGI
PHP-CGI是解释PHP脚本的程序,即PHP的解释器。
启动PHP-CGI,使用命令:php-cgi -b 127.0.0.1:9000
php-cgi只是个CGI程序,它自己本身只能解析请求,返回结果,不会进程管理,所以就出现了一些能够调度php-cgi进程的程序,比如说由lighthttpd分离出来的spawn-fcgi。PHP-FPM也是能够调度php-cgi的程序,在长时间的发展后,逐渐得到了大家的认可,也越来越流行。
PHP-CGI的不足

  1. php-cgi变更php.ini配置后需重启php-cgi才能让新的php-ini生效,不可以平滑重启;
  2. 直接杀死php-cgi进程,php就不能运行了。(PHP-FPM和Spawn-FCGI就没有这个问题,守护进程会平滑从新生成新的子进程)

Spawn-FCGI
Spawn-FCGI是一个通用的FastCGI管理服务器,它是lighttpd中的一部份,很多人都用Lighttpd的Spawn-FCGI进行FastCGI模式下的管理工作,不过有不少缺点。Spawn-FCGI目前已经独成为一个项目,更加稳定一些,也给很多Web 站点的配置带来便利。已经有不少站点将它与nginx搭配来解决动态网页。
参数含义如下:
-f 指定调用FastCGI的进程的执行程序位置,根据系统上所装的PHP的情况具体设置
-a 绑定到地址addr
-p 绑定到端口port
-s 绑定到unix socket的路径path
-C 指定产生的FastCGI的进程数,默认为5(仅用于PHP)
-P 指定产生的进程的PID文件路径
-u和-g FastCGI使用什么身份(-u 用户 -g 用户组)运行,Ubuntu下可以使用www-data,其他的根据情况配置,如nobody、apache等
PHP-FPM详解
PHP-FPM作为PHP源代码的一个补丁,是一个是只用于PHP的FastCGI进程管理器,旨在将FastCGI进程管理整合进PHP包中,负责管理一个进程池,来处理来自Web服务器的请求。必须将它patch到PHP源代码中,在编译安装PHP后才可以使用。
相对Spawn-FCGI,PHP-FPM在CPU和内存方面的控制都更胜一筹,而且前者很容易崩溃,必须用crontab进行监控,而PHP-FPM则没有这种烦恼。
注意,在PHP5.2及以前的版本,Fastcgi模块名称为 mod_fastcgi,需要另外下载源码安装,自从PHP5.3及以后的版本中,Fastcgi模块被改名为 php-fpm,并集成在PHP中,随PHP源码一起发布,不再是第三方的包了。PHP-FPM提供了更好的PHP进程管理方式,可以有效控制内存和进程、可以平滑重载PHP配置,在./configure的时候带 –enable-fpm参数即可开启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文件

php-fpm有两种执行方式, 与Apache一样,其进程数也可以根据设置分为动态和静态,可以根据服务器的实际需求来调整这两种不同的执行方式。
静态:直接开启指定数量的php-fpm进程,不再增加或者减少;
动态:开始的时候开启一定数量的php-fpm进程,当请求量变大的时候,动态的增加php-fpm进程数到上限,当空闲的时候自动释放空闲的进程数到一个下限。

参数介绍:

[pm;pm.max_children;pm.start_servers;pm.min_spare_servers;pm.max_spare_servers]
pm  #表示使用那种方式【static|dynamic】
在更老一些的版本中,dynamic被称作apache-like。这个要注意看配置文件给出的说明了
pm.max_children      #静态方式下开启的php-fpm进程数量
pm.start_servers     #动态方式下的起始php-fpm进程数量
pm.min_spare_servers #动态方式下的最小php-fpm进程数量
pm.max_spare_servers #动态方式下的最大php-fpm进程数量

如果pm设置为static,那么只有pm.max_children参数有效。系统会开启设置的数个php-fpm进程。
如果pm设置为dynamic,那么pm.max_children参数失效,后面3个参数有效。系统会在php-fpm运行开始的时候启动pm.start_servers个php-fpm进程,然后根据系统的需求动态在pm.min_spare_servers和pm.max_spare_servers之间调整php-fpm进程数。
那么对于服务器,选择哪种执行方式比较好呢?
事实上,跟Apache一样,运行的PHP程序在执行完成后,或多或少会有内存泄露的问题。这也是为什么开始的时候一个php-fpm进程只占用3M左右内存,运行一段时间后就会上升到20-30M的原因了。所以,动态方式因为会结束掉多余的进程,可以回收释放一些内存,所以推荐在内存较少的服务器或者VPS上使用。具体最大数量根据内存/20M 得到。比如说512M的VPS,建议pm.max_spare_servers设置为20。至于pm.min_spare_servers,则建议根据服务器的负载情况来设置,比较合适的值在5~10之间。
而对于内存比较大的服务器来说,设置为静态的话会提高效率。因为频繁开关php-fpm进程也会有时滞,所以内存够大的情况下开静态效果会更好。数量也可以根据 内存/30M 得到。比如说2GB内存的服务器,可以设置为50;4GB内存可以设置为100等。
DEMO参数如下:这样就可以最大的节省内存并提高执行效率

pm=dynamic
pm.max_children=20
pm.start_servers=5
pm.min_spare_servers=5
pm.max_spare_servers=20

PHP-FPM与spawn-CGI
PHP-FPM、Spawn-FCGI都是守护php-cgi的进程管理器。
PHP-FPM的使用非常方便,配置都是在PHP-FPM.ini的文件内,而启动、重启都可以从php/sbin/PHP-FPM中进行。更方便的是修改php.ini后可以直接使用PHP-FPM reload进行加载,无需杀掉进程就可以完成php.ini的修改加载
结果显示使用PHP-FPM可以使php有不小的性能提升。PHP-FPM控制的进程cpu回收的速度比较慢,内存分配的很均匀。
Spawn-FCGI控制的进程CPU下降的很快,而内存分配的比较不均匀。有很多进程似乎未分配到,而另外一些却占用很高。可能是由于进程任务分配的不均匀导致的.而这也导致了总体响应速度的下降。而PHP-FPM合理的分配,导致总体响应的提到以及任务的平均。
PHP-FPM官方文档http://php-fpm.org/about/
参考文档:
http://www.fastcgi.com/drupal/node/2
http://segmentfault.com/q/1010000000256516

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值