PHP运行模式汇总

PHP运行模式有4钟:

1)cgi 通用网关接口(Common Gateway Interface))
2) fast-cgi 常驻 (long-live) 型的 CGI
3) cli  命令行运行   (Command Line Interface)
4)web模块模式 (apache等web服务器运行的模块模式)
5)ISAPI(Internet Server Application Program Interface)

备注:在PHP5.3以后,PHP不再有ISAPI模式,安装后也不再有php5isapi.dll这个文件。要在IIS6上使用高版本PHP,必须安装FastCGI 扩展,然后使IIS6支持FastCGI。

1.  CGI(Common Gateway Interface)

CGI即通用网关接口(Common Gateway Interface),它是一段程序, 通俗的讲CGI就象是一座桥,把网页和WEB服务器中的执行程序连接起来,它把HTML接收的指令传递给服务器的执行程序,再把服务器执行程序的结果返还给HTML页。CGI 的跨平台性能极佳,几乎可以在任何操作系统上实现。 CGI已经是比较老的模式了,这几年都很少用了。

每有一个用户请求,都会先要创建cgi的子进程,然后处理请求,处理完后结束这个子进程,这就是fork-and-execute模式。 当用户请求数量非常多时,会大量挤占系统的资源如内存,CPU时间等,造成效能低下。所以用cgi方式的服务器有多少连接请求就会有多少cgi子进程,子进程反复加载是cgi性能低下的主要原因。

如果不想把 PHP 嵌入到服务器端软件(如 Apache)作为一个模块安装的话,可以选择以 CGI 的模式安装。或者把 PHP 用于不同的 CGI 封装以便为代码创建安全的 chroot 和 setuid 环境。这样每个客户机请求一个php文件,Web服务器就调用php.exe(win下是php.exe,linux是php)去解释这个文件,然后再把解释的结果以网页的形式返回给客户机。 这种安装方式通常会把 PHP 的可执行文件安装到 web 服务器的 cgi-bin 目录。CERT 建议书 CA-96.11 建议不要把任何的解释器放到 cgi-bin 目录。

这种方式的好处是把web server和具体的程序处理独立开来,结构清晰,可控性强,同时缺点就是如果在高访问需求的情况下,cgi的进程fork就会成为很大的服务器负担,想 象一下数百个并发请求导致服务器fork出数百个进程就明白了。这也是为什么cgi一直背负性能低下,高资源消耗的恶名的原因。

CGI模式安装:

CGI已经是比较老的模式了,这几年都很少用了,所以我们只是为了测试。

安装CGI模式需要注释掉
     LoadModule php5_module modules/libphp5.so 这行。如果不注释这行会一直走到handler模式。也就是模块模式。
     然后在httpd.conf增加action:
     Action application/x-httpd-php /cgi-bin/
     如果在/cgi-bin/目录找不到php-cgi.可自行从php的bin里面cp一个。
     然后重启apache,再打开测试页面发现Server API变成:CGI/FastCGI。说明成功切换为cgi模式。
          问题:

1)  如果cgi程序放在/usr/local/httpd/cgi-bin/里无法执行,遇到403或500错误的话
打开apache错误日志 有如下提示: Permission denied: exec of
可以检查cgi程序的属性,按Linux contexts文件 里定义的,/usr/local/httpd/cgi-bin/里必须是httpd_sys_script_exec_t 属性。  通过ls -Z查看,如果不是则通过如下命令更改:     chcon -t httpd_sys_script_exec_t /var/www/cgi-bin/*.cgi     如果是虚拟主机里的cgi,则参考问题2使之能正常使用普通的功能后,再通过chcon设置cgi文件的context为       
httpd_sys_script_exec_t即可。chcon -R -t httpd_sys_script_exec_t cgi-bin/

2) apache错误提示:…. malformed header from script. Bad header=
根据提示说明有header有问题,查看文件输出的第一句话是什么,应该类似于如下    
Content-type: text/plain; charset=iso-8859-1\n\n    
或者Content-type:text/html\n\n  
注意:声明好Content-type后要输出两个空行。

3)apache错误提示: Exec format error
脚本解释器设置错误。脚本第一行应该以'#!解释器路径'的形式, 填写脚本解释器的路径,如果是PERL程序,常见的路径为:     #!/usr/bin/perl 或 #!/usr/local/bin/perl           如果是PHP程序,不需要填写解释器路径,系统会自动找到PHP。

2.  Fastcgi模式

fast-cgi 是cgi的升级版本,FastCGI 像是一个常驻 (long-live) 型的 CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去 fork 一次 (这是 CGI 最为人诟病的 fork-and-execute 模式)。

FastCGI的工作原理是:

(1)、Web Server启动时载入FastCGI进程管理器【PHP的FastCGI进程管理器是PHP-FPM(php-FastCGI Process Manager)】(IIS ISAPI或Apache Module);

(2)、FastCGI进程管理器自身初始化,启动多个CGI解释器进程 (在任务管理器中可见多个php-cgi.exe)并等待来自Web Server的连接。

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

(4)、FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回Web Server。当FastCGI子进程关闭连接时,请求便告处理完成。FastCGI子进程接着等待并处理来自FastCGI进程管理器(运行在 WebServer中)的下一个连接。在正常的CGI模式中,php-cgi.exe在此便退出了。

在CGI模式中,你可以想象 CGI通常有多慢。每一个Web请求PHP都必须重新解析php.ini、重新载入全部dll扩展并重初始化全部数据结构。使用FastCGI,所有这些都只在进程启动时发生一次。一个额外的好处是,持续数据库连接(Persistent database connection)可以工作。

Fastcgi的优点:

1)从稳定性上看, fastcgi是以独立的进程池运行来cgi,单独一个进程死掉,系统可以很轻易的丢弃,然后重新分 配新的进程来运行逻辑.
2)从安全性上看,Fastcgi支持分布式运算. fastcgi和宿主的server完全独立, fastcgi怎么down也不会把server搞垮.
3)从性能上看, fastcgi把动态逻辑的处理从server中分离出来, 大负荷的IO处理还是留给宿主server, 这样宿主server可以一心一意作IO,对于一个普通的动态网页来说, 逻辑处理可能只有一小部分, 大量的图片等静态

FastCGI缺点:

说完了好处,也来说说缺点。从我的实际使用来看,用FastCGI模式更适合生产环境的服务器。但对于开发用机器来说就不太合适。因为当使用 Zend Studio调试程序时,由于 FastCGI会认为 PHP进程超时,从而在页面返回 500错误。这一点让人非常恼火,所以我在开发机器上还是换回了 ISAPI模式。

安装fastcgi模式:
安装apache路径是/usr/local/httpd/
安装php路径是/usr/local/php/

1)安装mod_fastcgi

wget http://www.fastcgi.com/dist/mod_fastcgi-2.4.6.tar.gz
tar zxvf mod_fastcgi-2.4.6.tar.gz
cd mod_fastcgi-2.4.6
cp Makefile.AP2 Makefile
vi Makefile,编辑top_dir = /usr/local/httpd
make
make insta

安装完后,

/usr/local/httpd/modules/多出一个文件:
mod_fcgid.so

2)重新编译php

./configure –prefix=/usr/local/php –enable-fastcgi –enable-force-cgi-redirect –disable-cli
make
make install

这样编译后,在PHP的bin目录下的php-cgi就是fastcgi模式的php解释器了
安装成功后,执行

php -v 输出
PHP 5.3.2 (cgi-fcgi).

这里输出带了cgi-fcgi

注意:

1. 编译参数不能加 –with-apxs=/usr/local/httpd/bin/apxs 否则安装出来的php执行文件是cli模式的
2  如果编译时不加–disable-cli则输出 PHP 5.3.2(cli)
3)配置apache

需要配置apache来以fastcgi模式运行php程序
vi httpd.conf

我们使用虚拟机的方式实现:

#加载fastcgi模块
LoadModule fastcgi_module   modules/mod_fastcgi.so
#//以静态方式执行fastcgi 启动了10进程
FastCgiServer /usr/local/php/bin/php-cgi -processes 10 -idle-timeout 150 -pass-header HTTP_AUTHORIZATION
<VirtualHost *:80>
   #
   DocumentRoot  /usr/local/httpd/fcgi-bin
   ServerName www.fastcgitest.com

   ScriptAlias /fcgi-bin/  /usr/local/php/bin/  #定义目录映射 /fcgi-bin/ 代替 /usr/local/php/bin/
   Options +ExecCGI
   AddHandler fastcgi-script .php .fcgi     #.php结尾的请求都要用php-fastcgi来处理
   AddType application/x-httpd-php .php   #增加MIME类型
   Action application/x-httpd-php /fcgi-bin/php-cgi #设置php-fastcgi的处理器: /usr/local/php/bin/php-cgi
 <Directory /usr/local/httpd/fcgi-bin/>
   Options Indexes ExecCGI
   Order allow,deny
   allow from all
 </Directory>
</VirtualHost>

4).restart 下apache,查看phpinfo,如果服务器信息是:
Apache/2.2.11 (Unix) mod_fastcgi/2.4.6之类的就说明安装成功了。
如果出现403的错误,查看下/usr/local/httpd/fcgi-bin/是否有足够的权限。
或者

<Directory />
  Options FollowSymLinks
  AllowOverride None
  Order deny,allow
  Deny from all
</Directory>

就可以了。
ps -ef|grep  php-cgi可以看见10个fastcgi进程在跑。

3.   CLI模式

cli是php的命令行运行模式,大家经常会使用它,但是可能并没有注意到(例如:我们在linux下经常使用 "php -m"查找PHP安装了那些扩展就是PHP命令行运行模式;有兴趣的同学可以输入php -h去深入研究该运行模式)

1.让 PHP 运行指定文件。

php script.php
php -f script.php

以上两种方法(使用或不使用 -f 参数)都能够运行脚本的script.php。您可以选择任何文件来运行,您指定的 PHP 脚本并非必须要以 .php 为扩展名,它们可以有任意的文件名和扩展名。

2.在命令行直接运行 PHP 代码。

php -r "print_r(get_defined_constants());"

在使用这种方法时,请您注意外壳变量的替代及引号的使用。
注: 请仔细阅读以上范例,在运行代码时没有开始和结束的标记符!加上 -r 参数后,这些标记符是不需要的,加上它们会导致语法错误。

3.通过标准输入(stdin)提供需要运行的 PHP 代码。

以上用法给我们提供了非常强大的功能,使得我们可以如下范例所示,动态地生成 PHP 代码并通过命令行运行这些代码:

$ some_application | some_filter | php | sort -u >final_output.txt

4. 模块模式

模块模式是以mod_php5模块的形式集成,此时mod_php5模块的作用是接收Apache传递过来的PHP文件请求,并处理这些请求,然后将处理后的结果返回给Apache。如果我们在Apache启动前在其配置文件中配置好了PHP模块(mod_php5), PHP模块通过注册apache2的ap_hook_post_config挂钩,在Apache启动的时候启动此模块以接受PHP文件的请求。

除了这种启动时的加载方式,Apache的模块可以在运行的时候动态装载,这意味着对服务器可以进行功能扩展而不需要重新对源代码进行编译,甚至根本不需要停止服务器。我们所需要做的仅仅是给服务器发送信号HUP或者AP_SIG_GRACEFUL通知服务器重新载入模块。但是在动态加载之前,我们需要将模块编译成为动态链接库。此时的动态加载就是加载动态链接库。 Apache中对动态链接库的处理是通过模块mod_so来完成的,因此mod_so模块不能被动态加载,它只能被静态编译进Apache的核心。这意味着它是随着Apache一起启动的。

Apache是如何加载模块的呢?我们以前面提到的mod_php5模块为例。首先我们需要在Apache的配置文件httpd.conf中添加一行:

该运行模式是我们以前在windows环境下使用apache服务器经常使用的,而在模块化(DLL)中,PHP是与Web服务器一起启动并运行的。(是apache在CGI的基础上进行的一种扩展,加快PHP的运行效率)

LoadModule php5_module modules/mod_php5.so 

这里我们使用了LoadModule命令,该命令的第一个参数是模块的名称,名称可以在模块实现的源码中找到。第二个选项是该模块所处的路径。如果需要在服务器运行时加载模块,可以通过发送信号HUP或者AP_SIG_GRACEFUL给服务器,一旦接受到该信号,Apache将重新装载模块,而不需要重新启动服务器。

5 ISAPI模式

  ISAPI(Internet Server Application Program Interface)是微软提供的一套面向Internet服务的API接口,一个ISAPI的DLL,可以在被用户请求激活后长驻内存,等待用户的另一个请求,还可以在一个DLL里设置多个用户请求处理函数,此外,ISAPI的DLL应用程序和WWW服务器处于同一个进程中,效率要显著高于CGI。(由于微软的排他性,只能运行于windows环境)

  PHP作为Apache模块,Apache服务器在系统启动后,预先生成多个进程副本驻留在内存中,一旦有请求出现,就立即使用这些空余的子进程进行处理,这样就不存在生成子进程造成的延迟了。这些服务器副本在处理完一次HTTP请求之后并不立即退出,而是停留在计算机中等待下次请求。对于客户浏览器的请求反应更快,性能较高。

6.  php在Nginx中运行模式(Nginx+ PHP-FPM)

使用FastCGI方式现在常见的有两种stack:ligthttpd+spawn-fcgi;另外一种是nginx+PHP-FPM(也可以用spawn-fcgi)。

A、如上面所说该两种结构都采用FastCGI对PHP支持,因此HTTPServer完全解放出来,可以更好地进行响应和并发处理。因此lighttpd和nginx都有small, but powerful和efficient的美誉。

B、该两者还可以分出一个好坏来,spawn-fcgi由于是lighttpd的一部分,因此安装了lighttpd一般就会使用spawn-fcgi对php支持,但是目前有用户说ligttpd的spwan-fcgi在高并发访问的时候,会出现上面说的内存泄漏甚至自动重启fastcgi。即:PHP脚本处理器当机,这个时候如果用户访问的话,可能就会出现白页(即PHP不能被解析或者出错)。
另一个:首先nginx不像lighttpd本身含带了fastcgi(spawn-fcgi),因此它完全是轻量级的,必须借助第三方的FastCGI处理器才可以对PHP进行解析,因此其实这样看来nginx是非常灵活的,它可以和任何第三方提供解析的处理器实现连接从而实现对PHP的解析(在nginx.conf中很容易设置)。nginx可以使用spwan-fcgi(需要一同安装lighttpd,但是需要为nginx避开端口,一些较早的blog有这方面安装的教程),但是由于spawn-fcgi具有上面所述的用户逐渐发现的缺陷,现在慢慢减少使用nginx+spawn-fcgi组合了。

C、由于spawn-fcgi的缺陷,现在出现了新的第三方(目前还是,听说正在努力不久将来加入到PHP core中)的PHP的FastCGI处理器,叫做PHP-FPM(具体可以google)。它和spawn-fcgi比较起来有如下优点:
由于它是作为PHP的patch补丁来开发的,安装的时候需要和php源码一起编译,也就是说编译到php core中了,因此在性能方面要优秀一些;
同时它在处理高并发方面也优于spawn-fcgi,至少不会自动重启fastcgi处理器。具体采用的算法和设计可以google了解。
因此,如上所说由于nginx的轻量和灵活性,因此目前性能优越,越来越多人逐渐使用这个组合:nginx+PHP/PHP-FPM

7.  总结

目前在

HTTPServer这块基本可以看到有三种stack比较流行:

(1)Apache+mod_php5
(2)lighttp+spawn-fcgi
(3)nginx+PHP-FPM

三者后两者性能可能稍优,但是Apache由于有丰富的模块和功能,目前来说仍旧是老大。有人测试nginx+PHP-FPM在高并发情况下可能会达到Apache+mod_php5的5~10倍,现在nginx+PHP-FPM使用的人越来越多。

(0)

相关推荐

  • 前端实现文件的断点续传(前端文件提交+后端PHP文件接收)

    早就听说过断点续传这种东西,前端也可以实现一下.断点续传在前端的实现主要依赖着HTML5的新特性,所以一般来说在老旧浏览器上支持度是不高的. 本文通过断点续传的简单例子(前端文件提交+后端PHP文件接收),理解其大致的实现过程 还是先以图片为例,看看最后的样子 一.一些知识准备 断点续传,既然有断,那就应该有文件分割的过程,一段一段的传. 以前文件无法分割,但随着HTML5新特性的引入,类似普通字符串.数组的分割,我们可以可以使用slice方法来分割文件. 所以断点续传的最基本实现也就是:前端通

  • PHP之将POST数据转化为字符串的实现代码

    主要用途就是记录POST过来的参数: 以下函数主要原理还是应用递归方式,将多维数组转化为一维数组进行,最后进行数组转字符串处理既可拿到POST过来的数据字符串化: 核心代码: /** * 应用于LOG记录POST参数使用 * * @version 0.0.1 * @Author Chenjl <ciwdream@gmail.com> * * @return string */ function getPostLog(array $_data = array(),$n = ''){ $_gPOS

  • php实现的http请求封装示例

    本文实例讲述了php的http请求封装.分享给大家供大家参考,具体如下: /** * 发送HTTP请求方法,目前只支持CURL发送请求 * @param string $url 请求URL * @param array $params 请求参数 * @param string $method 请求方法GET/POST * @return array $data 响应数据 */ protected function http($url, $params, $method = 'GET', $hea

  • php使用FFmpeg接口获取视频的播放时长、码率、缩略图以及创建时间

    FFmpeg是一个视频插件,我们可以利用调用FFmpeg接口来获取视频的相关信息,包括视频的播放时长,视频的码率,视频的缩略图以及视频创建时间,本文章向大家介绍php如何使用FFmpeg接口获取视频信息,需要的朋友可以参考一下. FFmpeg获得视频文件的缩略图: function getVideoCover($file,$time,$name) { if(empty($time))$time = '1';//默认截取第一秒第一帧 $strlen = strlen($file); // $vid

  • PHP数组的定义、初始化和数组元素的显示实现代码

    从ASP初入门到PHP,感觉到PHP的强大之一就是内置函数的丰富,比如先前学习的PHP日期时间函数,读写文件的相关函数等都无不表明了PHP的更专业.更令用户的使用得心应手. 一开始我对PHP函数的丰富功能很兴奋,随着对越来越多近乎变态多的函数接触之后,突然联想到了ASP内置函数的稀少,要完成某项特殊功能,常须自定义函数,随着应用的在增多,自己居然也有了一套常用的函数库.然而现在在PHP中,这些功能早已被标准化.规范化而浓缩为内置函数直接使用,曾经的ASP开发人员成为了PHP的普通用户. 但转念一

  • 深入了解PHP中的Array数组和foreach

    1. 了解数组 PHP 中的数组实际上是一个有序映射.映射是一种把 values 关联到 keys 的类型.详细的解释可参见:PHP.net中的Array数组    . 2.例子:一般的数组 这里,我通过一个简单的例子,并使用图形方式来了解数组. $a = array(3 => 'a', 1 => 'b', 2 => 'c'); echo var_dump($a); [注]:使用箭头描述数组$a各个单元对应某一内存地址的数据值(实际上,它内部结构采用HashTable结构,可以参考鸟哥写

  • PHP中获取文件创建日期、修改日期、访问时间的方法

    php获取文件创建时间.修改时间常用代码 filemtime ( string filename ) 返回文件上次被修改的时间,出错时返回 FALSE.时间以 Unix 时间戳的方式返回,可用于 date(). 例如:$a=filemtime("log.txt"); echo "修改时间:".date("Y-m-d H:i:s",$a); filectime ( string filename ) 返回文件上次 inode 被修改的时间,如果出错

  • PHP获取访问页面HTTP状态码的实现代码

    废话不说了直接上代码 核心代码: /** * 获取远程URL的HTTP状态 * * @version 0.0.1 * @Author Chenjl * * @param string $url 远程URL * @param string $data ture[返回HTTP状态数组] | false[返回状态数值] * * @return mixed */ function getHeaders($url,$data=FALSE){ $_headers = get_headers($url,1);

  • php 输出json及显示json中的中文汉字详解及实例

    php 输出json及显示json中的中文汉字 在php中,我们经常需要将数组输出json,只需要使用json_encode函数处理一下数组即可,但有的时候数组里面有中文,使用json_encode函数处理后中文字符被编码成了Unicode,如何才能在json中显示中文呢?请看下文. 首先介绍一下php输出json格式: 一种最简单的用法,就是把数组直接输出为json,如下: <?php $arr = array('p1'=>'ni"hao','p2'=>2,'ch'=>

  • PHP利用超级全局变量$_POST来接收表单数据的实例

    利用$_POST超级全局变量接收表单的数据,然后利用echo输出到页面. 下面是代码: <!doctype html> <html> <head> <title>利用超级全局变量$_POST接收表单</title> <meta http-equiv="content-type" contnet="text/html" charset="utf-8"/> </head&g

  • php 时间time与日期date之间的使用详解及区别

    php时间time与日期date之间的使用区别 1.time()函数 PHP中的time()函数,使用echo输出来看是一个很长的整数,里面包含了日期和时间,是计算后的一个值.如果要得到Y-m-d H:i:s这样的日期格式,那么可以使用date方法: date('Y-m-d H:i:s', time()); echo输出它即可得到:2016-1-5 10:20:11 2.日期格式与字符串 我们自己可以构建一个日期格式的字符串,如:2015-1-1 10:20:11.可以使用strtotime()

  • PHP利用超级全局变量$_GET来接收表单数据的实例

    我们在linux上用 touch php_get.html php_get.php创建两个文件. php_get.html文件的代码如下: <!doctype html> <html> <head> <title>超级全局变量$_GET来接收提交的数据,然后返回信息</title> <meta http-equiv="contnet-type" content="text/htm" charset=&

  • php使用file函数、fseek函数读取大文件效率对比分析

    php读取大文件可以使用file函数和fseek函数,但是二者之间效率可能存在差异,本文章向大家介绍php file函数与fseek函数实现大文件读取效率对比分析,需要的朋友可以参考一下. 1. 直接采用file函数来操作 由于 file函数是一次性将所有内容读入内存,而PHP为了防止一些写的比较糟糕的程序占用太多的内存而导致系统内存不足,使服务器出现宕机,所以默认情况下限制只能最大使用内存16M,这是通过php.ini里的 memory_limit = 16M 来进行设置,这个值如果设置-1,

随机推荐