怎样优化Apache服务器的性能

通过挤出Apache服务器的每一分潜力你可以让你的网站留给别人的印象大大改观,特别是对一些动态网站更是如何。这篇文章主要涉及到对 Apache服务器的安装和设置如何进行优化,这也是你最有控制权的部分。

测试与提高性能

Apache服务器已经被设计得尽可能的快,即使你用一台配置不高的机器,用不着进行太复杂的设置,它的响应内容就足以塞满以前的各种窄带连接。但随网站内容日益复杂和带宽的增加,对Apache进行优化以取得更好的性能变得日益重要起来。

如果优化的结果仅仅是极小的性能提升那真是浪费时间。试想一下,你花了好几个小时甚至几天调整Apache的各种参数但结果仅是几个百分点的性能提升?因此,在优化前你做的第一步应该是测试你目前的服务器的性能水平以便决定如何优化你的服务器并衡量优化的效果。

关于对Apache的测试我们已经不是第一次提到了(见《冲出水面》一文),如同我们以前提到的,确定到底是哪一部分导致的瓶颈往往是一件困难的事,是因为 Apache本身的设置问题还是由于你使用的动态网站程序环境?关于查找是否是因为网站程序引起的问题已经超出了本文的范围,这里我们主要讲一下提高 Apache服务器速度的一些通常做法以及它如何与构成WEB网站的其它组件进行交互。

主机硬件

Apache所在的机器与操作系统环境是对性能影响最大因素,很明显,一以368的PC与一台P4或双处理器的机器不会有同样的性能。不过,如果不涉及硬件的改变,我们可以做的最大的事是首先看一下Apache是否运行在一台专用的服务器上,如果与其它应用共用一台服务器肯定会影响服务器的性能。

在大多数情况下,告别是对静态网站而言,内存数量是一个影响性能的关键因素,因为它决定了Apache可以缓存多少内容。它缓存的内容越多,在硬盘上读取内容的机会就越少,而存取硬盘上的特定文件是一件很费时的操作。如果你的网站主要是一些静态内容,你最好使用mod_cache 选项,如果你的内存足够大,可以使用mod_mem_cache选项。

第一个选项将信息缓存在磁盘上,当它与mod_include选项一起使用时会有很好的效果,这个选项在建立一个页面时在缓存中保存它的最终版本。使用mod_mem_cache将缓存内容保存在一个可以被所有Apache进程共享的内存堆中。

使用更快的磁盘或进一步使用RAID可以提高Apache对磁盘文件的访问速度。3

注意,如果你做了下面的所有这些优化,一个硬件的(而非软件)升级方案是更好的选择。

最后一个谈到的关于硬件的问题是CPU能力,这对动态内容网站的影响很大,动态内容越多要求越高。

主机环境

不管是使用何种操作系统,下面这些原则都是适用的:

●尽可能减少非必要的后台运行的程序数目。如果你真的很关心服务

器性能,你甚至可以关闭一些通常被认为是必要的后台服务。比如在UNIX下面,你可以关闭NFS服务,任何打印服务甚至邮件发送服务(如果不使用这些服务),在Windows系统下,使用控制面板优化系统和缓存,当然,对于必要的服务(如MySQL)仍然需要运行。

●避免使用系统。如果在服务器运行时你利用它进行其它工作(如编译软件,编辑文件或配置机器)你必将降低服务器提供的性能。如果你必须在上面安装一些组件,你可以在其它机器上编译好后拷备到服务器上。

●让你的系统组件维持在最新。虽然这主要是从安全角度的建议,不过软件补丁往往提供了网络和I/O方面的性能提升。

Apache程序

下面,就谈到Apache本身了。

首先你确认一下是否Apache在编译时是否仅包含了你的网站需要的组件。这意味着,你可以忽略一些用不着的组件。这使它占用的内存更少,而且,它也表示你不用意外的激活一些选项降低服务器的性能。

静态还是动态

灵活性常是一些Apache管理员考虑的主要因素,但灵活性也有代价,使用动态载入模块非常方便,但它将导致性能下降,因为在需要时模块才会被载入。不过动态模块也有利于减少服务器对内存的需求。

为了装Apache安装成静态模式,使用设置脚本定义你需要的模块,但是不要将它们定义为共享的(例如:使用-enable-rewrite而不要用-enable-rewrite=shared,也不要用共享选项-enable-so)。

模块设置

如果你使用Apacher的静态模式,你必须小心选项载入的模块,这是静态模式带来的一个开销-载入的模块越多,占用的内存越大,对于使用分叉多线程模型的程序这个效果更是明显。

注意一些项目是被自动包含的,因此你需要显式的指定包含或禁用需要的模块。另外要记住如果需要包含进来一些如认证,PHP或 mod_perl这样的第三方模块,你需要WEB服务(Web service),使用configure -help命令来查看可以使用的选项列表。

服务器设置

如果你的环境已经建立Apache也已经经过优化,就可以查看你的设置文件来进行下一步的优化措施。一个好的方法就是简化你的设置文件将文件中的指示(directives)减少到几百行内,首先是删除掉那些注释行,进而删除任何非必要的内容。

简化设置文件

第一步是简化设置设置文件,它并不带来任何直接的性能提升,但它将使设置文件易于使用减少你出错的机会。

在进行优化之前,从一个默认提供的设置文件开始是一个不错的主意。这些文件常被放在Apache的设置目录中,文件名为 httpd.conf.orig或者 httpd-std.conf,不要使用如performance-std.conf类似名称的文件,从长远的观点看,如果你准备在里面加入大量的附加设置信息,它决不是一个好起点。另一方面,如果你的目标是建立一个很快的静态WEB服务器,这可能是让服务器运行起来的最简单方法。

如果你熟悉Apache的设置指示用法或乐意浏览帮助文件,你可以从设置文件中删除所有的注释内容,因为它们经常让实际的指示内容变得难找,你也可以删除对当前平台上用不到的多处理机方式(MPM)的引用。

禁用模块

现在,我们已经得到了一个清爽的设置文件,下面我们可以开始删除其中我们系统用不到的元素,特别是:

●HostnameLookups(主机名查找),这增加了处理每个请求的开销,首先,服务器会对DNS系统做一个反向查询以找出客户系统的主机名,然后又进行正向查询看获得的主机名是否真实指向客户的IP。大多数情况下,你可以简单的关闭这个功能,如果你经常处理服务器日志,这个工作完全可以在以后进行。你可以通过在设置文件中加入指示HostnameLookups off来关闭这个功能。

●符号连接。当打开这个选项时,Apache将检查每个请求中是否包含对符号连接的引用,这将对请求中包含的每个路径调用一次lstat()系统调用。除非你准备使用符号连接,否则用 Options -FollowSymLinks 来关掉它。

●服务器状态信息。尽管这对测试与监控服务器很有用,但它也为服务器带来了额外的开销,你可以通过寻找任何类似SetHandler server-status的指示来关闭,如果可能,你可以在安装Apache时移除这个模块。

●在可以更精确的时候尽可能不要使用通配符之类的灵活选项,例如,对于DirectoryIndex指示,明确的指定设置文件列表,最常用的放在最前。

●除非你有很好的理由否则就允许CGI的执行,将似有的CGI文件放到一个特定的目录并为之设定正确的权限,这避免了Apache对每一个请求都要判断一次要求的是一个静态文件还是一个动态文件。

用日志

写入日志信息是一个很花费时间的工作,尽管Apache保持日志文件的打开状态以节省打开文件的时间,但仍然得花费不少的时间。如果没有必要

存储日志信息,你可以关闭这个选项以节省出更多的处理器时间,只需要在设置文件中把日志那一行注释掉就可以关掉它。

如果必须保留日志,你可以关闭HostnameLookups选项(见上文)然后把日志文件拷备到另一台机器上做进一步分析。

简化目录级的设置

htaccess文件可以极大的扩展Apache的设置参数,而无需每次你改变设计都要编辑Apache主设置文件,但对这个文件的使用也降低了服务器的性能。

如果使用这个文件,Apache必需首先在当前目录中查找是否存在这个文件,如果存在就解析这个文件并在当前目录中应用文件中的设置。更坏的是,Apache不仅要查看当前的目录,还要查看当前目录的所有上层目录是否包括htaccess文件以根据所有这些文件最终确定设置。

如果你想最优化服务器的性能,你应该禁止使用htaccess文件,任何基本目录的设置都可以在主设置文件中进行,而主设置文件仅在服务器启动时解析一次。

为了禁用htaccess文件,在任何节里加上指示AllowOverride None。

多处理方式设置

多处理方式(Multi-Processing Module/MPM)他允许特定平台处理多个并发连接。MPM模块是平台相关的,对于Unix、Windows、BeOS、和NetWare有不同的解决方案,一些平台有不止一个方案可以选择。对大多数用户而言,对于特定平台的默认设置已经工作得很好,而精确调整这些参数是一个费时的工作。不过如果你想最大限度的挖掘Apache的潜力,你必须调整这些设置。

对大多数平台而言,只有一种MPM可选,不过在UNIX下则有两个选项:prefork与worker,prefork模式生成多个相同的 Apache进程,而worker模式创建多个线程。通常而言,对于只有一到两颗处理器的系统,prefork模式工作得更好,而对于拥有更多处理器的系统,线程模型工作得更有效率。

不管哪种情况,MaxClients指示是最有效的提高服务器性能的方法,它控制了Apache可以处理的最大并发连接数。

优化静态内容

如果你的WEB服务器使用了大量静态内容或者你分别用两个WEB服务器处理动态和静态内容,那么你现在的主要目标就是缩短服务器发送被请求内容的响应时间,最简单的方法就是使用mod_cache缓存模块。你可以使用mod_disk_cache和mod_mem_cache来分别提供基于磁盘的缓存和基于内存的缓存。

你可以查看关于mod_cache的说明文件以取得进一步的信息。

优化动态内容

动态内容可能是所有WEB服务器中最消费时间的部分,特别是使用CGI的时候,一个简单的程序都可能会把响应时间增加好几秒。

使用基于脚本的方案的一大好处是它们在Apache里装入了解释器,这就减少了执行时再装入解释器的时间,一些方案还把解析过的脚本缓存起来,这样下一次遇到同样的请求就可以直接执行而无需再次解析。

对特定系统的调整优化很复杂而且很花时间,而且你需要调整特定的脚本以利用优化的成果。

不过对动态内容的优化效果是非常明显的,仅仅是把perl脚本的执行模式从CGI转到mod_perl就可以减少多达70%的执行时间,如果我们进一步,还可以使用到数据库的持久连接或在多次请求之间缓存信息,这对电子商务网站非常有用,它也减小了不同请求间重复装载信息的开销。

总结

尽管Apache是一个高可定制的功能强大且相当复杂的服务器软件,我们很有兴趣的注意到即使是Apache的标准安装也可以得到不错的性能。调整 Apache的设置参数是一个可以轻易显著提高服务器性能的方法。但不幸的是,常常我们在Apache里最无法控制的内容-例如网站的动态内容脚本和 CGI是影响网站性能的最重要方面,如果你管理一个典型的Apache服务器你会发现Apache响应一个传入连接以及最后把内容发送给客户的所花费的时间是以毫秒记的,而等待所需数据资源的时间常常达到几秒钟。

当然,这并不是说我们的优化工作没什么意义,优化的效果日积月累也不可小视。另外,重要的是,通过简化你的设置文件,你可以大大减小服务器的管理负担。

优化Apache服务器的重负荷

Apache在一天两万个请求确实不大,但如果在高峰时期出现,而晚间或其它时间没有,呈正态分布,且均是需要时间的下载服务,那负载还是很大的。

Apache允许为请求开的最大进程数是256,MaxClients的限制是256.如果用户多了,用户就只能看到Waiting for reply….然后等到下一个可用进程的出现。这个最大数,是Apache的程序决定的-它的NT版可以有1024,但Unix版只有256,你可以在src/include/httpd.h中看到:

#ifndef HARD_SERVER_LIMIT
#ifdef WIN32
#define HARD_SERVER_LIMIT 1024
#else
#define HARD_SERVER_LIMIT 256
#endif
#endif

你可以把它调到1024,然后再编译你的系统。记得在httpd.conf里也要更改相应配置,缺省好象是150。就下面的机器来说,调到512顶死了,如果再高,系统受不了。

另外,一些系统也限制了一个用户的最大进程数。你可以用ulimit -u 来看。Linux一般是256。因此你要真想让Apache超过这个数,就得调整 这个参数:

ulimit -u unlimited

这个参数要在Apache运行之前修改,因此建议加到apachectl里:

case $ARG in
start)
if [ $RUNNING -eq 1 ]; then
echo “$0 $ARG: httpd (pid $PID) already running”
continue
改成
case $ARG in
start)
ulimit -u unlimited
if [ $RUNNING -eq 1 ]; then
echo “$0 $ARG: httpd (pid $PID) already running”
continue

Apache优化配置

1、服务器个数的硬上限HARD_SERVER_LIMIT的修改:
在FREEBSD和LINUX等UNIX操作系统下APACHE缺省的最大进程数是256个,需要修改apache_1.3.xx/src /include/httpd.h
#ifndef HARD_SERVER_LIMIT
#ifdef WIN32
#define HARD_SERVER_LIMIT 1024
#elif defined(NETWARE)
#define HARD_SERVER_LIMIT 2048
#else
#define HARD_SERVER_LIMIT 2560 将原来的HARD_SERVER_LIMIT 256 后面加个“0”
#endif
#endif
注解:
APACHE缺省的最大用户数是256个:这个配置对于服务器内存还是256M左右的时代是一个非常好的缺省设置,现在随便找一台PC内存配置都与其相当,服务器就更不要说了。所以256个进程的硬限制对于一台高于256M内存的机器来说是太浪费了,而且APACHE的软上限max_client是受限于HARD_SERVER_LIMIT的,因此如果WEB服务器内存大于256M,都应该调高APACHE的HARD_SERVER_LIMIT。根据个人的经验:2560已经可以满足大部分小于2G内存的服务器的容量规划了(APACHE的软上限的规划请看后面)。

2、APACHE的编译:通用的编译选项能使安装过程标准化
./configure –prefix=/another_driver/apache/ –enable-shared=max –enable-module=most

注解:
–prefix=/another_driver/apache/: 作为web服务器硬盘的工作量是不可忽略的,为了降低硬盘的损耗可以将服务数据和系统完全分开,这样能提高了数据的访问速度,更重要的,大大便于系统升级,备份和恢复。

–shared-module=max:使用动态加载会有5%的性能损耗,但是这样做更有助于模块升级、系统升级风险降低、安装过程标准化。

–enable-module=most:用most可以将一些不常用的module编译进来,例如后面分析的mod_expire是就不在 apache的缺省常用模块中。

3、精简apache:apache的缺省配置文件一般比较大,可以去掉无聊的注释精简一下。

grep -v “#” httpd.conf.default >httpd.conf

#服务端口,缺省是8080,建议将整个APACHE配置调整好后再将服务端口改到正式服务的端口
Port 8080 => 80

#服务器名:缺省没有
自己搞定

#最大服务进程数:根据服务容量预测设置
MaxClients 256 => 800

#缺省启动服务后的服务进程数:等服务比较平稳后,按平均负载下的httpd个数设置就可以
StartServers 5 => 200

不要修改:
以前也有些文章说要修改:
MinSpareServers 5 => 100
MaxSpareServers 10 => 200

个人看来:缺省值已经是非常优化的了,而且让APACHE自己调整进程个数还是比较好的。

特别修改:
在solaris或一些比较容易出现内存泄露的应用上:
MaxRequestsPerChild 0 =>3000

4、应用模块和工具的安装配置:由于使用模块动态加载的模式,所以可以方便的配置来把APACHE调整成你需要的,最好把不常用模块全部清除,无论是安全考虑还是效率考虑。

不需要的模块包括:
#LoadModule env_module libexec/mod_env.so
#LoadModule negotiation_module libexec/mod_negotiation.so
#LoadModule status_module libexec/mod_status.so
#server side include已经过时了,淘汰。
#LoadModule includes_module libexec/mod_include.so
#LoadModule autoindex_module libexec/mod_autoindex.so不需要将没有缺省index文件的目录下所有文件列出
#LoadModule cgi_module libexec/mod_cgi.so尽量不使用CGI:一直是APACHE安全问题最多的地方
#LoadModule asis_module libexec/mod_asis.so
#LoadModule imap_module libexec/mod_imap.so
#LoadModule action_module libexec/mod_actions.so
#LoadModule access_module libexec/mod_access.so不使用安全校验可以大大提高访问速度
#LoadModule auth_module libexec/mod_auth.so
#LoadModule setenvif_module libexec/mod_setenvif.so

最好保留的有:
#LoadModule config_log_module libexec/mod_log_config.so用于定制log格式
#LoadModule mime_module libexec/mod_mime.so用于增加文件应用的关联
#LoadModule dir_module libexec/mod_dir.so用于缺省index文件:index.php等

可用可不用的鸡肋:
#需要在~/username/下调试php可以:LoadModule userdir_module libexec/mod_userdir.so
#需要将以前的URL进行转向或者需要使用CGI script-alias可以: LoadModule alias_module libexec/mod_alias.so

常用的模块:
最常用的应该是php和JAVA WEB应用的wrapper,从性能上讲:mod_gzip可以减少40%左右的流量,从而减少机器用于传输的负载,而mod_expires可以减少 10%左右的重复请求,让重复的用户请求CACHE在本地,根本不向服务器发出请求。

建议将所有MODULE的配置都放到:
/path/to/php_src/configure –with-apxs=/path/to/apache/bin/apxs –with-other-modules-you-need

参考文档(有时间MM可以上以下网站参考):

Apache
http://httpd.apache.org

php
http://www.php.net

Resin
http://www.caucho.com

mod_gzip
http://www.remotecommunications.com/apache/mod_gzip/

Cronolog
http://www.cronolog.org

mod_expires
http://httpd.apache.org/docs/mod/mod_expires.html

1、服务器个数的硬上限HARD_SERVER_LIMIT的修改:
在FREEBSD和LINUX等UNIX操作系统下APACHE缺省的最大进程数是256个,需要修改apache_1.3.xx/src /include/httpd.h
#ifndef HARD_SERVER_LIMIT
#ifdef WIN32
#define HARD_SERVER_LIMIT 1024
#elif defined(NETWARE)
#define HARD_SERVER_LIMIT 2048
#else
#define HARD_SERVER_LIMIT 2560 将原来的HARD_SERVER_LIMIT 256 后面加个“0”
#endif
#endif
注解:
APACHE缺省的最大用户数是256个:这个配置对于服务器内存还是256M左右的时代是一个非常好的缺省设置,现在随便找一台PC内存配置都与其相当,服务器就更不要说了。所以256个进程的硬限制对于一台高于256M内存的机器来说是太浪费了,而且APACHE的软上限max_client是受限于HARD_SERVER_LIMIT的,因此如果WEB服务器内存大于256M,都应该调高APACHE的HARD_SERVER_LIMIT。根据个人的经验:2560已经可以满足大部分小于2G内存的服务器的容量规划了(APACHE的软上限的规划请看后面)。
2、APACHE的编译:通用的编译选项能使安装过程标准化
./configure –prefix=/another_driver/apache/ –enable-shared=max –enable-module=most
注解:
–prefix=/another_driver/apache/: 作为web服务器硬盘的工作量是不可忽略的,为了降低硬盘的损耗可以将服务数据和系统完全分开,这样能提高了数据的访问速度,更重要的,大大便于系统升级,备份和恢复。
–shared-module=max:使用动态加载会有5%的性能损耗,但是这样做更有助于模块升级、系统升级风险降低、安装过程标准化。
–enable-module=most:用most可以将一些不常用的module编译进来,例如后面分析的mod_expire是就不在apache 的缺省常用模块中。
3、精简apache:apache的缺省配置文件一般比较大,可以去掉无聊的注释精简一下。
grep -v “#” httpd.conf.default >httpd.conf
#服务端口,缺省是8080,建议将整个APACHE配置调整好后再将服务端口改到正式服务的端口
Port 8080 => 80
#服务器名:缺省没有
自己搞定
#最大服务进程数:根据服务容量预测设置
MaxClients 256 => 800
#缺省启动服务后的服务进程数:等服务比较平稳后,按平均负载下的httpd个数设置就可以
StartServers 5 => 200
不要修改:
以前也有些文章说要修改:
MinSpareServers 5 => 100
MaxSpareServers 10 => 200
个人看来:缺省值已经是非常优化的了,而且让APACHE自己调整进程个数还是比较好的。
特别修改:
在solaris或一些比较容易出现内存泄露的应用上:
MaxRequestsPerChild 0 =>3000
4、应用模块和工具的安装配置:由于使用模块动态加载的模式,所以可以方便的配置来把APACHE调整成你需要的,最好把不常用模块全部清除,无论是安全考虑还是效率考虑。
不需要的模块包括:
#LoadModule env_module libexec/mod_env.so
#LoadModule negotiation_module libexec/mod_negotiation.so
#LoadModule status_module libexec/mod_status.so
#server side include已经过时了,淘汰。
#LoadModule includes_module libexec/mod_include.so
#LoadModule autoindex_module libexec/mod_autoindex.so不需要将没有缺省index文件的目录下所有文件列出
#LoadModule cgi_module libexec/mod_cgi.so尽量不使用CGI:一直是APACHE安全问题最多的地方
#LoadModule asis_module libexec/mod_asis.so
#LoadModule imap_module libexec/mod_imap.so
#LoadModule action_module libexec/mod_actions.so
#LoadModule access_module libexec/mod_access.so不使用安全校验可以大大提高访问速度
#LoadModule auth_module libexec/mod_auth.so
#LoadModule setenvif_module libexec/mod_setenvif.so
最好保留的有:
#LoadModule config_log_module libexec/mod_log_config.so用于定制log格式
#LoadModule mime_module libexec/mod_mime.so用于增加文件应用的关联
#LoadModule dir_module libexec/mod_dir.so用于缺省index文件:index.php等
可用可不用的鸡肋:
#需要在~/username/下调试php可以:LoadModule userdir_module libexec/mod_userdir.so
#需要将以前的URL进行转向或者需要使用CGI script-alias可以: LoadModule alias_module libexec/mod_alias.so
常用的模块:
最常用的应该是php和JAVA WEB应用的wrapper,从性能上讲:mod_gzip可以减少40%左右的流量,从而减少机器用于传输的负载,而mod_expires可以减少 10%左右的重复请求,让重复的用户请求CACHE在本地,根本不向服务器发出请求。
建议将所有MODULE的配置都放到:
/path/to/php_src/configure –with-apxs=/path/to/apache/bin/apxs –with-other-modules-you-need