PHP网站提速三大“软”招

文/李鲲程
随着网络的普及,网站已经渗透到了每个行业,但是由于目前专线费用让很多企业和个人难以承受,所以共享带宽成为很多网站的首选方案。费用虽然降低了但是一个新的问题很快就出现了,那就是共享带宽的网速很慢,有时甚至让人无法忍受。如何能让自己的网站快起来,成为人们关心的问题,笔者结合亲身实践来讲讲软办法的一些实际应用,希望能够对读者有所帮助。
笔者采用的是Linux操作系统,Apache+PHP的网站构建方法。 代码优化
通常要求程序员要有好的编程习惯,尽量减少冗余代码的出现,目前也有好多工具能够完成这项功能,对于一般的html文件,用于减少冗余的减肥工具很多,而对于PHP程序来说这样的工具就不太多了,但是ZendTechnologies的ZendOptimizer是一款非常好的代码优化工具,可以免费从ZendTechnologies的网站上获得。ZendOptimizer的使用方法也非常简单,只要将下载的ZendOptimizer-1[1].0.0-PHP_4.0.4-Linux_glibc21-i386.tar.gz文件解压缩,将其中的ZendOptimizer.so文件拷贝到/usr/local/Zend/lib目录下,然后修改php.ini文件,在最后添加以下几行:
显示说明ZendOptimizer工作正常 zend_optimizer.optimization_level=15
zend_extension=”/usr/local/Zend/lib/ZendOptimizer.so”
设置完成后重启Apache服务器,编写一段PHP程序: <? Phpinfo(); ?>
一般来说ZendOptimizer能将系统的效率提升30%~40%,这是用户最关心的。
压缩页面
HTTP1.1协议支持页面压缩传送,也就是说服务器把一个页面压缩传送到客户端,然后在客户端将页面解压缩再显示给客户。在服务器端有两种传输方式,一种是页面事先已经压缩好了,传送时只要将压缩页面传送到客户端就行,这种适用于静态网页多的情况,但是对于大多数站点,动态页面比较多,这种方法不太适合,因为很多传到客户端的页面其实是没有的,是服务器接到客户端用户请求动态产生的,所以就要求每生成一个动态页面都要在传到客户端以前先打包压缩。从PHP的4.0.4版以后,可以在php.ini文件中增加一行配置“output_handler=ob_gzhandler”,这样每个动态生成的页面在传送到客户端之前都会进行压缩,但是根据PHP官方站点的说明,这个参数不能与“zlib.output_compression=on”参数同时使用,因为容易引起PHP工作不正常,另外它只能压缩PHP程序的动态生成的页面,对于大量的静态页面尤其是图像文件就不行了。但是mod_gzip模块为Apahe提供了将静态页面在传给客户端以前先压缩的功能,它的压缩比最大能到10,一般情况下可以到3,也就是说网站的传输速率一下提高了三倍多。要想使用mod_gzip功能首先要下载mod_gzip.c或mod_gzip.so文件,如果下载的是.c文件还要用Apache带的工具将它转化为.so文件才能使用,方法是运行下面的命令:
-i-amod_gzio.c cpmod_foo.so/path/to/apache/libexec/mod_gzip.so
chmod755/path/to/apache/libexec/mod_foo.so
系统会在/path/to/apache/etc/中自动激活该模块,如果下载的是.so文件则要将该文件拷贝到相应的目录下,然后在文件中添加LoadModulegzip_modulelibexec/mod_gzip.so,使模块生效。需要注意两点,第一,要想使用.so文件,Apache必须包含了mod_so模块;第二,如果下载的是.so文件,它是与Apache的版本有关的,要注意下载的版本与自己使用的Apache是否一致,如果是.c文件就没有这个问题。模块生效后还要对Apache进行相应的配置,需要在文件中加入一些参数:
mod_gzip_onYes mod_gzip_minimum_file_size1002
mod_gzip_maximum_file_size0 mod_gzip_maximum_inmem_size60000
mod_gzip_item_includefile”..gif102SINADOUBLE_QUOTATION
mod_gzip_item_includefile”.txt102SINADOUBLE_QUOTATION
mod_gzip_item_includefile”.html102SINADOUBLE_QUOTATION
mod_gzip_item_excludefile”.css102SINADOUBLE_QUOTATION
使用了压缩模块后,当用户访问站点时会在日志文件中记录相应的信息,比如“mod_gzip:OKIn:file_lengthOut:gzipfile_length”,表示该页面传输中使用了gzip功能,输入文件、输出文件大小都有说明。
文件缓存
这种方法通常是针对PHP、PERL等CGI程序而言的,因为这些程序有一个共同的特征就是接到用户的请求后不是马上将结果返回给用户,而是经过解释器解释执行后将执行结果返回给客户,这期间通常都要涉及到数据库的访问。这样就会出现一个问题,当两个用户访问同一个页面时,系统将分别对两个请求进行操作,但事实上这两个操作可能是一模一样的,这样无形当中增加了系统的负担。所以通常的解决办法是在系统内存中开辟出一段空间,当用户第一次访问页面后将执行结果存放在该内存中,当有用户再一次访问该页面时,系统就将页面直接从内存中调出而不需要重新解释执行,这段内存空间就叫缓存。目前流行的缓存管理程序有两个,一个是FastCGI,另一个是ZendTechnologies公司的ZendCache。FastCGI主要是针对Perl、C、C++等CGI脚本程序设计的,可以有效地利用内存作缓存,来自客户端的请求都会被传送到FastCGI应用服务程序,FastCGI处理用户的请求后将结果返回给用户。一般的CGI程序这时将结束进程自动退出,但是FastCGI进程继续保持,这时它在接到新的用户请求后不必建立新的进程,可以立即处理用户请求,也就是说CGI程序建立进程顺序执行然后退出,而FastCGI程序顺序执行并永远循环。
ZendCache的管理界面
要想使用FastCGI首先要把FastCGI编译到Apache中,方法非常简单,这里就不说明了,还要在文件里作设置:
AddHandlerfastcgi-script.fcg.fcgi.fpl OptionsExecCGIIndexesIncludes
这样FastCGI就可以正常工作了,下面是FastCGI程序员手册中的一段例子程序:
#!fcgi-savvy-perl useFCGI;#初始化 #Initializationcode =0;
#Responseloop while(FCGI::accept>=0){ #FastCGI建立循环体
print”Content-type:text/html”;#程序执行
print”<head><title>FastCGIDemoPage(perl)</title></head>”;
print”<h1>FastCGIDemoPage(perl)</h1>”;
print”ThisiscomingfromaFastCGIserver.<BR>”;
print”Runningon<EM>publish152.internal.sina.com.cn</EM>to<EM></EM><BR>”;
++; print”Thisisconnectionnumber”; }
FastCGI对Perl等CGI程序的功能非常强大,但是它对PHP程序确是无能为力的,而且需要在编程时增加内容,也就是说它需要一些人为的因素才能发挥作用。相比之下ZendTechnologies公司的ZendCache针对PHP的缓存功能是很强大的,只要安装了该软件,程序员就像编写其他PHP程序一样,不需要增加代码,就可以实现缓存功能,有利于系统升级,十分方便。它是一个付费软件。它有缓存功能并能通过图形界面对其进行管理,其中:CacheControl页面,可以配置ZendCache,显示其当前状态,还能启动和停止ZendCache功能;Scripts页面,ZendCache的内容,包括每个文件的状态,还可以根据点击次数和缓存占有大小选择文件;Benchmark页面,可以测试ZendCache的缓存效果,并以图形方式给出显示,它测试的是每秒钟完成PHP请求的次数。
它的安装、验证方法与ZendOptimizer基本相同,这里就不详细说明了,感兴趣的读者可以参考用户手册,它的强大功能和便利的管理方法确实让人心动。
以上是网站提速常见的几种方法,对于不同的网站需要采用不同的手段,所对应的提速方案也不尽相同,但总体上不外乎是以上提到的三招,读者可以根据自己的实际情况具体问题具体分析。
注意:考虑到客户端软件的复杂性,因为有些客户端软件可能不支持某些特性,比如,mod_gzip对页面进行压缩,但是如果客户端使用的是Netscape就不行,因为它不能把接收到的压缩页面解压缩,导致页面不能正常显示。

HTTP1.1协议支持页面压缩传送,也就是说服务器把一个页面压缩传送到客户端,然后在客户端将页面解压缩再显示给客户。在服务器端有两种传输方式,一种是页面事先已经压缩好了,传送时只要将压缩页面传送到客户端就行,这种适用于静态网页多的情况,但是对于大多数站点,动态页面比较多,这种方法不太适合,因为很多传到客户端的页面其实是没有的,是服务器接到客户端用户请求动态产生的,所以就要求每生成一个动态页面都要在传到客户端以前先打包压缩。从PHP的4.0.4版以后,可以在php.ini文件中增加一行配置“output_handler

作者:松下客来源:网易社区
PHP最大的优点之一显然在于它的速度快。一般情况下PHP总是具有足够的速度支持Web内容动态生成,许多时候你甚至无法找出比它更快的方法。然而,当你不得不面对庞大的访问量、高负荷的应用、有限的带宽以及其他各种带来性能瓶颈的因素时,你可能会问问自己是否可以做点什么让网站运行得更好。或许只要加上一个很不起眼的免费模块,你的PHP应用性能以及Web服务器响应速度就会有显著的改善。本文讨论的就是如何进一步提高php应用的性能,给用户以更美妙的浏览感受。本文分三个方面阐述提高PHP应用性能的各种技术,并介绍各个领域的知名产品。
代码优化
首先我们来看看代码优化。注意,这里的代码优化可不是指把代码写得更加美观漂亮,因为这恐怕已经是众所周知没有必要继续讨论了;另外,如果你已经考虑到了速度问题,很可能你早就对PHP的源代码作了一些优化。不过,有些工具却能够自动地帮助我们完成这些繁杂的工作,如ZendOptimizer就是这样一个工具。ZendOptimizer可以从ZendTechnologies免费得到,但你必须同意它的许可约定,注意它不是以GPL方式发行。ZendOptimizer获取由ZendEngine运行时编译生成的中间代码,并对它进行优化,从而使得中间代码具有更快的执行效率。
ZendOptimizer的安装方法非常简单,你只需下载为自己所用平台提供的预编译版本,把下面两行代码加入到php.ini,然后重新启动Web服务器即可:
zend_optimizer.optimization_level=15
zend_extension=”/path/to/ZendOptimizer.so” zend_loader.enable=Off
这里额外增加的第三行代码是可选的。禁止zend_loader似乎能够让ZendOptimizer的速度更快一点,所以在php.ini中加上这行代码是值得的。注意:只有当你不使用ZendEncoderRuntime时,你才可以禁用zend_loader。
缓存
如果你想要让自己庞大的PHP应用有更好的性能表现,采用缓存也是一种很好的方法。现在已经有许多缓存方案可供选择,其中包括:ZendCache,APC,和AfterburnerCache。
所有这些产品都属于“缓存模块”。当第一次出现对.php文件的请求时,它们会在Web服务器内存中保存PHP的中间代码,此后就用“经过编译”的版本响应后继的请求。这种方法确实能够改善应用的性能,因为它使得磁盘访问量减低到了最少的程度,代码直接在内存中运行使得服务器响应请求的速度大大提高。当然,缓存模块还会监视PHP源文件的变化,必要时重新缓存页面,从而防止了用户得到的页面仍旧由过时的PHP代码生成。由于缓存模块能够明显地降低服务器的负载、提高PHP应用的响应效率,因此它们非常适合于负载较大的网站使用。
如何选择这些缓存产品
ZendCache是ZendTechnologies公司的商业软件,而ZendTechnologies就是前面提到的那个为我们提供PHP引擎和免费ZendOptimizer的公司。ZendCache确实是名不虚传!对于大型的PHP页面,你可以感觉到第一次运行之后速度就会有所提高,而且服务器也会有更多的可用资源。遗憾的是这个产品并不免费,不过在有些情形下它仍旧是物超所值。
AfterburnerCache是来自BwareTechnologies的免费缓存模块,当前这个产品还是Beta版。AfterburnerCache的做法看起来与ZendCache差不多,但它对性能的改善程度不能与ZendCache相比,而且它还不能与ZendOptimizer一起工作。
APC是AlternativePHPCache的缩写,它是来自CommunityConnect的又一个免费缓存模块。这个产品已经具有足够的稳定性供正式场合使用,而且它看起来也能在很大程度上提高响应请求的速度。
内容压缩
前面我们讨论了几种提高PHP应用性能的方法,下面来看看使得浏览者感到网站速度太慢的另外一个重要因素:下载速度。如果PHP应用在内部Intranet上运行,而且每一台客户机都以100MB/s的速度连接到服务器,那么下载速度应该不是什么问题。然而,如果服务器还要为慢腾腾的Modem用户提供服务,那么值得考虑内容压缩。大多数浏览器都根据IETF标准支持用gzip进行内容压缩。这意味着你可以用gzip压缩内容然而发送给浏览器,由浏览器解压缩数据之后再显示页面,这整个过程对用户来说完全透明。至于服务器端的内容压缩,现在已经有许多不同的方法可供使用。
例如,来自RemoteCommunications的免费Apache模块mod_gzip就具有为支持这类内容编码的浏览器压缩静态Web内容的能力。对于绝大多数静态Web内容,mod_gzip都非常有效。mod_gzip可以方便地编译到Apache里面,也可以作为DSO使用。据Remotecommunications公司说,mod_gzip也能够压缩来自mod_php、mod_perl等的动态内容。我试了一次又一次,但看来还是不行。我看了许多关于mod_gzip的论坛和文章,看来到了mod_gzip的下一个版本这个问题有望得到解决。在此之前,我们可以在网站的静态部分使用mod_gzip。
然而有时我们确实需要压缩动态内容,所以必须找找其他办法。有一种办法是使用class.gzip_encode.php,这是一个可以用来压缩页面内容的PHP类,具体方法是在PHP脚本的开头和末尾调用该类的某些函数。如果要在网站级实现这个方案,可以从php.ini文件的auto_prepend以及auto_append指令调用这些函数。这种方法虽然有效,但它无疑为高负载的网站带来了更多的开销。关于如何使用这个类的详细说明,请参见它的源代码。它的源代码说明相当完善,作者告诉了你所有你必须知道的事情。
PHP4.0.4有一个新的输出缓存句柄ob_gzhandler,它与前面的类相似,但用法不同。使用ob_gzhandler时要在php.ini中加入的内容如下:
output_handler=ob_gzhandler;
这行代码使得PHP激活输出缓存,并压缩它发送出去的所有内容。如果由于某种原因你不想在php.ini中加上这行代码,你还可以通过PHP源文件所在目录的.htaccess文件改变默认的服务器行为,语法如下:
php_valueoutput_handlerob_gzhandler 或者是从PHP代码调用,如下所示:
ob_start(“ob_gzhandler”);
采用输出缓存句柄的方法确实非常有效,而且不会给服务器带来什么特殊的负荷。但必须注意的是,NetscapeCommunicator对压缩图形的支持不佳,因此除非你能够保证所有用户都使用IE浏览器,否则你应该禁止压缩JPEG和GIF图形。一般地,对于所有其他文件,这种压缩都有效,但建议你针对各种浏览器都分别进行测试,特别是当你使用了特殊的插件或者数据查看器时这一点尤其重要。
使用前面介绍的各种技术,你能够显著地改善网站的性能表现,但应该注意的是:
PHP可能是、也可能不是性能瓶颈所在。务必仔细地观察每一个和应用性能有关的因素,比如数据库等。
单纯使用本文技术只能在一定限度之内提高Web服务器的性能。因此在归咎于PHP以及它的缓存之前,不妨看看是否应该升级服务器以及是否可以引入负载平衡技术。
不要低估内容压缩的作用。虽然你在100MB/s的LAN连接下看到Web应用响应非常迅速,但使用Modem连接的用户不会,他们只会抱怨你那100Kb的HTML页面实在过于庞大。

1. 提高PHP的运行效率
PHP的优点之一是速度很快,对于一般的网站应用,可以说是已经足够了。不过如果站点的访问量很高、带宽窄或者其它的因素令服务器产生性能瓶颈的时候,你可能得想想其它的办法来进一步提高PHP的速度了。
1.1. 代码优化 1、用i+=1代替i=i+1。符合c/c++的习惯,效率还高。
2、尽可能的使用PHP内部函数。自己编写函数之前要详细查阅手册,看有没有相关的函数,否则费力不讨好。
3、能使用单引号字符串尽量使用单引号字符串。单引号字符串的效率要高于双引号字符串。
4、用foreach代替while遍历数组。遍历数组时foreach的效率明显高于while循环,而且不需要调用reset函数。两种遍历方法如下:
程序1: 复制代码 代码如下: reset ; while
= each { echo “Key: $key; Value: $valuen”; } 程序2: 复制代码 代码如下: foreach ($arr as $key
=> $value) { echo “Key: $key; Value: $valuen”; } 1.2. 压缩页面

ob_gzhandler”,这样每个动态生成的页面在传送到客户端之前都会进行压缩,但是根据PHP官方站点的说明,这个参数不能与“zlib.output_compression

on”参数同时使用,因为容易引起PHP工作不正常,另外它只能压缩PHP程序的动态生成的页面,对于大量的静态页面尤其是图像文件就不行了。但是mod_gzip模块为Apahe提供了将静态页面在传给客户端以前先压缩的功能,它的压缩比最大能到10,一般情况下可以到
3,也就是说网站的传输速率一下提高了三倍多。要使用mod_gzip还要对Apache进行相应的配置,需要在httpd.conf文件中加入一些参数:
复制代码 代码如下: mod_gzip_on Yes
mod_gzip_minimum_file_size 1002 mod_gzip_maximum_file_size 0
mod_gzip_maximum_inmem_size 60000 mod_gzip_item_include file
“..gif102SINA>DOUBLE_QUOTATION mod_gzip_item_include file
“.txt102SINA>DOUBLE_QUOTATION mod_gzip_item_include file
“.html102SINA>DOUBLE_QUOTATION mod_gzip_item_exclude file
“.css102SINA>DOUBLE_QUOTATION 1.3. 文件缓存
这种方法通常是针对PHP、PERL等CGI程序而言的,因为这些程序有一个共同的特征就是接到用户的请求后不是马上将结果返回给用户,而是经过解释器解释执行后将执行结果返回给客户,这期间通常都要涉及到数据库的访问。这样就会出现一个问题,当两个用户访问同一个页面时,系统将分别对两个请求进行操作,但事实上这两个操作可能是一模一样的,这样无形当中增加了系统的负担。所以通常的解决办法是在系统内存中开辟出一段空间,当用户第一次访问页面后将执行结果存放在该内存中,当有用户再一次访问该页面时,系统就将页面直接从内存中调出而不需要重新解释执行,这段内存空间就叫缓存。目前流行的缓存管理程序是Zend
Technologies公司的Zend Cache。 2. 执行系统外部命令
PHP作为一种服务器端的脚本语言,象编写简单,或者是复杂的动态网页这样的任务,它完全能够胜任。但事情不总是如此,有时为了实现某个功能,必须借助于操作系统的外部程序,这样可以做到事半功倍。
在PHP中调用外部命令,可以用如下三种方法来实现: 2.1. 用PHP提供的专门函数
PHP提供共了3个专门的执行外部命令的函数:system。 system() 原型:string
system (string command [, int return_var])
system()函数很其它语言中的差不多,它执行给定的命令,输出和返回结果。第二个参数是可选的,用来得到命令执行后的状态码。
例子: system(“/usr/local/bin/webalizer/webalizer”); exec() 原型:string
exec (string command [, string array [, int return_var]])
exec类似,也执行给定的命令,但不输出结果,而是返回结果的最后一行。虽然它只返回命令结果的最后一行,但用第二个参数array可以得到完整的结果,方法是把结果逐行追加到array的结尾处。所以如果array不是空的,在调用之前最好用unset()最它清掉。只有指定了第二个参数时,才可以用第三个参数,用来取得命令执行的状态码。
例子: 复制代码 代码如下: exec; exec;
exec(“/bin/ls -l”, $res, $rc); passthru() 原型:void passthru (string
command [, int return_var])
passthru()只调用命令,不返回任何结果,但把命令的运行结果原样地直接输出到标准输出设备上。所以passthru()函数经常用来调用象pbmplus(Unix下的一个处理图片的工具,输出二进制的原始图片的流)这样的程序。同样它也可以得到命令执行的状态码。
例子: 复制代码 代码如下:
header(“Content-type: image/gif”); passthru(“./ppmtogif hunte.ppm”);
2.2. 用popen()函数打开进程
上面的方法只能简单地执行命令,却不能与命令交互。但有些时候必须向命令输入一些东西,如在增加Linux的系统用户时,要调用su来把当前用户换到root才行,而su命令必须要在命令行上输入root的密码。这种情况下,用上面提到的方法显然是不行的。
popen()函数打开一个进程管道来执行给定的命令,返回一个文件句柄。既然返回的是一个文件句柄,那么就可以对它读和写了。在PHP3中,对这种句柄只能做单一的操作模式,要么写,要么读;从PHP4开始,可以同时读和写了。除非这个句柄是以一种模式打开的,否则必须调用pclose()函数来关闭它。
例子1 $fp=popen; 例子2 复制代码 代码如下:
/* PHP中如何增加一个系统用户 下面是一段例程,增加一个名字为james的用户,
root密码是 verygood。仅供参考 */ $sucommand = “su –login root
–command”; $useradd = “useradd “; $rootpasswd = “verygood”; $user =
“james”; $user_add = sprintf(“%s “%s %s””,$sucommand,$useradd,$user);
$fp = @popen; @fputs; @pclose; 3. 养成良好的程序风格
在很多情况下PHP最可贵的特点也可能是它最薄弱的环节就是它的语法松散性。
PHP能够如此广泛的被使用,因为它使得许多没有经验的Web开发者能够制作出强大的应用程序,而用不着过多的考虑规划、连贯性和文档。不幸的是,正是以上的特点,很多的PHP源代码很臃肿,很难阅读甚至无法维护。决定代码可维护性的重要因素是代码的格式和注释。一个工程的所有代码应该以贯穿始终的形式组织。以下介绍的是如何在PHP程序中养成良好的程序代码风格。
3.1. 缩进
开发者所有的代码应该完全按照缩进的方式书写。这是提高代码可读性最基本的措施。即使你没有注释你的代码,缩进对于让其他人读懂你的代码也是非常大的帮助。
3.2. 增加注释 在编程时添加注释是一个好的习惯.PHP
允许在页面代码中添加注释,具体的注释方法与C语言注释语法相同,在脚本中可以加注释。可以用
“/*” 和 “*/” 来注释一段话。可用双斜杠“//”作为注释符。 3.3. 控制结构
这个很大程度上取决于个人口味。我仍然可以看到很多的控制结构代码不带分支语句造成可读性非常差,如???你使用IF语句时不带分支,不但可读性变差,当其他人修改你的程序时,还会造成很多的bug。请看下例:
不好的例子: if echo ‘A was equal to 1’;
这是非常难以辨认的。它能够正常工作,但是除了你之外,别人根本不会赞赏这句代码。
有改进的例子: if echo ‘A was equal to 1’;
现在至少这句代码可以读懂了,但是仍然没有很好的可维护性。如果当$a==1的时候我希望一个附加的事件发生,或者需要添加分支呢?如果后来的程序员忘记了添加大括弧或者else关键字,那么程序中将出现bug。
完美的例子 复制代码 代码如下: if { echo
‘A was equal to 1’; //很容易的可以添加其他代码 } elseif { //其他操作 }
请注意在if和elseif后面的空格,这会将本语句和函数调用区分开来,此外,虽然在elseif的执行程序段中没有语句,只有注释,表面上显得多余可是却给以后维护程序的程序员给予了非常方便的提示,并且非常利于添加功能。
3.4. 利用 Include 来实现功能模块化
可以将常用的功能函数存于一个PHP文件,在其它PHP页中要用其中的功能时,将包含函数的PHP文件包含在调用函数的PHP文件中.这时可使用
Include 函数。具体语法为: include; 使用时应该注意: 1、应避免自包含,即
File1 包含
File1;在多个文件中有包含语句时,应避免间接自包含即循环包含,如File1包含File2,File2包含File3,File3包含File1.
2、被包含的脚本语言的类型必须是PHP语言类型或脚本语句段。

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图