服务器型号:

 

型号:DELL1750

cpu:Intel Xeon(TM) CPU 3.06GHz

内存 :1G

硬盘:70/70/70

操作系统:FreeBSD 4.8p-STABLE

 

主要针对的应用需求:

峰值:800次/s

日pv流量一千万。

每个文件最大0.5k字节,都是html文件.

使用内存文件系统。

 

目录:

简单介绍模块化思想

具体模块定制

影响性能的关键指标MPM

其他apache性能优化配置

简单性能测试

 

 

简单介绍模块化思想:

在UNIX系统上, Apache采用了多进程模型。多进程模型中, 其子进程处理客户请求, 父进程用于管理子进程. 当系统过载时父进程会再启动几个子进程, 当系统空闲时, 父进程会杀掉几个子进程. 子进程的数目在"MinSpareServers"和"MaxSpareServers"之间. 而且, 每个子进程处理的请求个数也是有限制的, 这可以解决诸如内存泄漏等问题. 所有的进程状态都被记录在share memory中. 由于每个进程的状态记录在其中的一小块内存上, 它通常也只读写这一块内存, 因此, Apache没有使用什么同步机制.

  Apache 2.0中加入了很多的核心改进和新功能,如Unix线程、多协议支持、新的构建系统、对非Unix平台的更佳支持、IPv6支持、新的Apache API、过滤器、多语言错误响应、原生的Windows NT Unicode支持、更简单化的配置,以及升级的正则表达式库等。它当然还包括对许多模块的重要改进,同时也加入了一些新的模块。

 

  Apache是模块化的服务器,核心服务器种只包含了功能最常用的模块,而扩展功能由其他模块提供。设置过程中,你必须指定需要包含的模块。文档中有模块清单备查,其中状态为"Base"的模块会被默认地包含进核心服务器,如果你不需要包含某个模块(比如mod_userdir),则必须明确地禁用它;其他状态的模块(比如mod_expires),也必须明确启用以使之包含进核心服务器。

 

  Apache有两种使用模块的方法,其一是永久性包含进核心;如果操作系统支持动态共享对象(DSO),而且能为autoconf所检测,则模块还可以被动态编译。DSO模块的存储是独立与核心的,可以被核心使用由mod_so模块提供的运行时刻配置指令包含或排除。如果编译中包含有任何动态模块,则mod_so模块会被自动包含进核心。如果希望核心能够装载DSO,而不实际编译任何动态模块,需要明确指定--enable-so。

具体模块定制:

编译和包含是两个不同的概念。编译是指这个模块被编译了,要想使用它,只用简单的修改httpd.conf加上LoadModule xxx_module  libexec/mod_xxx.so 明确指出。

 

用以前命令可以查看缺省时已编译和包含进去的模块。不用显式的--enable-MODULE[=shared]和LoadModule 操作。就已经可以使用的。

[yangbin1@vHost-RH9 conf]$ ../bin/httpd -l

Compiled in modules:

 

  core.c   //Apache HTTP 服务器提供的核心功能。必须要有的。

 

  mod_access.c  //1.安全认证大大降低访问速度,建议disable it .

  mod_auth.c          //1.安全认证大大降低访问速度,建议disable it .

  mod_include.c  //4.server side include已经过时了,建议disable it .

  mod_log_config.c //6.用于定制log格式.最好保留.

  mod_env.c         //5.修改传送到 CGI 脚本和 SSI 页面的系统环境(变量)。一般说来,可以不需要。

  mod_setenvif.c //1.安全认证大大降低访问速度,建议disable it .

  prefork.c    //Implements a non-threaded, pre-forking web server。参考下面的mpm介绍。

 

  http_core.c  //Apache HTTP 服务器提供的核心功能。必须要有的。

 

  mod_mime.c   //6.用于增加文件应用的关联。最好保留。

  mod_status.c  //5.Provides information on server activity and performance 。一般说来,可以不需要。

  mod_autoindex.c //3.不需要将没有缺省index文件的目录下所有文件列出,建议disable it .

  mod_asis.c               //2.尽量不使用CGI:一直是Apache安全问题最多的地方,建议disable it .

  mod_cgi.c                //2.尽量不使用CGI:一直是Apache安全问题最多的地方,建议disable it .

  mod_negotiation.c  //5.内容协商, 以根据浏览器提供的设置选择不同媒介类型、语言、字符集和编码的最佳表现, 还有对来自浏览器的不完整内容协商信息作智能处理的能力。一般说来,可以不需要。

  mod_dir.c   //用于缺省index文件:index.php等。我们现在的应用不需要这个。看情况而定。

  mod_imap.c           //2.尽量不使用CGI:一直是Apache安全问题最多的地方,建议disable it .

  mod_actions.c         //2.尽量不使用CGI:一直是Apache安全问题最多的地方,建议disable it .

  mod_userdir.c     //7.比如:需要在~/username/下调试php.可用可不用.建议disable it .

  mod_alias.c    //7.比如:需要将以前的URL进行转向或者需要使用CGI script-alias.建议disable it .

  mod_so.c     //8.如果编译中包含有任何动态模块,则mod_so模块会被自动包含进核心。如果希望核心能够装载DSO,而不实际编译任何动态模块,需要明确指定--enable-so。我们的应用使用静态编译,不需要它。建议disable it . 

下面讨论以下默认没有安装的几个重要的模块。。(除了prefork)

常用的模块:

最常用的可能就是php和JAVA应用服务器的前端,我们当前应用不需要。此外,从性能上讲利用mod_gzip可以减少40%左右的流量,减少机器用于传输的负载,建议使用。我们使用的文件比较小,可以看看压缩算法的时间开销和 传输的负载的减小是不是合算。 而 mod_expires可以减少10%左右的重复请求,让重复的用户对指定的页面请求结果都CACHE在本地,根本不向服务器发出请求。但是我们使用的是内存文件系统,关于cache的优化可以完全不予考虑。

基于反相代理的WEB加速:

squid和mod_proxy都可以实现反相代理加速。而基于缓存的代理加速比起原有WEB服务,速度会有数量级的提升。同样内存文件系统不需要。

 

影响性能的关键指标MPM:

MPM(Multi-Processing Modules,多道处理模块)。MPM看起来和其它Apache模块非常类似。与其他类型模块不同的是,Apache必须有一个且仅有一个MPM处在运行中。。 指定MPM的方法

$ ./configure --help|grep mpm

显示如下:

--with-mpm=MPM

Choose the process model for Apache to use.

MPM={beos|worker|prefork|mpmt_os2| perchild|leader|threadpool}

Beos、mpmt_os2分别是BeOS和OS/2上缺省的MPM,perchild主要设计目的是以不同的用户和组的身份来运行不同的子进程。这在运行多个需要CGI的虚拟主机时特别有用,会比1.3版中的SuExec机制做得更好。leader和threadpool都是基于worker的变体,还处于实验性阶段,某些情况下并不会按照预期设想的那样工作,所以Apache官方也并不推荐使用。因此,我们主要阐述prefork和worker这两种和性能关系最大的产品级MPM 。

 

如果不用“--with-mpm”显式指定某种MPM,prefork就是Unix平台上缺省的MPM。

prefork本身并没有使用到线程,2.0版使用它是为了与1.3版保持兼容性;prefork用单独的子进程来处理不同的请求,进程之间是彼此独立的,这也使其成为最稳定的MPM之一。

prefork的工作原理是,控制进程在最初建立“StartServers”个子进程后,为了满足MinSpareServers设置的需要创建一个进程,等待一秒钟,继续创建两个,再等待一秒钟,继续创建四个……如此按指数级增加创建的进程数,最多达到每秒32个,直到满足MinSpareServers设置的值为止。这就是预派生(prefork)的由来。这种模式可以不必在请求到来时再产生新的进程,从而减小了系统开销以增加性能。

下面是prefork的默认配置段:

 

<IfModule prefork.c>

StartServers         5  //

MinSpareServers      5  //设置了最小的空闲进程数。

MaxSpareServers     10  //设置了最大的空闲进程数,如果空闲进程数大于这个值,Apache会自动kill掉一些多余进程。这个值不要设得过大,但如果设的值比MinSpareServers小,Apache会自动把其调整为MinSpareServers+1。如果站点负载较大,可考虑同时加大MinSpareServers和MaxSpareServers。

MaxClients         150  // MaxClients是这些指令中最为重要的一个,设定的是Apache可以同时处理的请求,是对Apache性能影响最大的参数。其缺省值150是远远不够的,如果请求总数已达到这个值(可通过ps -ef|grep http|wc -l来确认),那么后面的请求就要排队,直到某个已处理请求完毕。这就是系统资源还剩下很多而HTTP访问却很慢的主要原因。系统管理员可以根据硬件配置和负载情况来动态调整这个值。虽然理论上这个值越大,可以处理的请求就越多,但Apache默认的限制不能大于256(在2.0中源于#define DEFAULT_SERVER_LIMIT 256)。如果把这个值设为大于256,那么Apache将无法起动。事实上,256对于负载稍重的站点也是不够的。在Apache 1.3中,这是个硬限制。如果要加大这个值,必须在“configure”前手工修改的源代码树下的src/include/httpd.h中查找256,就会发现“#define HARD_SERVER_LIMIT 256”这行。把256改为要增大的值(如4000),然后重新编译Apache即可。在Apache 2.0中新加入了ServerLimit指令,使得无须重编译Apache就可以加大MaxClients。ServerLimit使用也是单独添加一行在这就可以了。如果ServerLimit的值再这定义超过了20000,就要修改server/mpm/prefork/prefork.c  #define MAX_SERVER_LIMIT 20000。将20000改成更大的值。

 

MaxRequestsPerChild  0  //设置的是每个子进程可处理的请求数。每个子进程在处理了“MaxRequestsPerChild”个请求后将自动销毁。0意味着无限,即子进程永不销毁。虽然缺省设为0可以使每个子进程处理更多的请求,但如果设成非零值也有两点重要的好处:可防止意外的内存泄漏;在服务器负载下降的时侯会自动减少子进程数。

</IfModule>

 

 

worker的工作原理是,由主控制进程生成“StartServers”个子进程,每个子进程中包含固定的ThreadsPerChild线程数,各个线程独立地处理请求。同样,为了不在请求到来时再生成线程。

每个进程可以拥有的线程数量是固定的。 服务器会根据负载情况做增加或减少进程数量的调整。单个控制进程负责子进程的建立。每个子进程可以建立由ThreadsPerChild指定的固定数量的线程。然后,由独立的线程监听并处理到来的连接。

Apache总是试图维持一个备用的或者说空闲的服务线程池。 如此,客户端无须等待线程或进程的建立即可得到处理。 最初建立进程的数量由StartServers指令所决定。 其后,Apache检测所有进程中空闲线程的总数,并新建或结束进程使总数维持在MinSpareThreads和MaxSpareThreads所指定的范围以内。 由于这个过程是自动调整的,几乎没有必要修改这些指令的缺省值。 同时可以得到处理的客户端的最大数量取决于MaxClients指令,而进程建立的最大数量取决于ServerLimit指令。ServerLimit乘以ThreadsPerChild必须大于等于MaxClients。

下面是worker的默认配置段:

 

<IfModule worker.c>

StartServers         2

MaxClients         150  //设置了所有子进程中的线程总数。如果现有子进程中的线程总数不能满足负载,控制进程将派生新的子进程。

MinSpareThreads     25  //设置了最少的空闲线程数

MaxSpareThreads    75  //设置了最多的空闲线程数. MinSpareThreads和MaxSpareThreads的最大缺省值分别是75和250.也就是说在这里定义不要超过这个。

ThreadsPerChild     25

MaxRequestsPerChild  0  //它是worker MPM中与性能相关最密切的指令。ThreadsPerChild的最大缺省值是64,如果负载较大,64也是不够的。这时要显式使用ThreadLimit指令,它的最大缺省值是20000。上述两个值位于源码树server/mpm/worker/worker.c中的以下两行:

#define DEFAULT_THREAD_LIMIT 64

#define MAX_THREAD_LIMIT 20000 

这两行对应着ThreadsPerChild和ThreadLimit的限制数。最好在configure之前就把64改成所希望的值。注意,不要把这两个值设得太高,超过系统的处理能力,从而因Apache不起动使系统很不稳定。

</IfModule>

 

Worker模式下所能同时处理的请求总数是由子进程总数乘以ThreadsPerChild值决定的,应该大于等于MaxClients。如果负载很大,现有的子进程数不能满足时,控制进程会派生新的子进程。默认最大的子进程总数是16,加大时也需要显式声明ServerLimit(最大值是20000)。这两个值位于源码树server/mpm/worker/worker.c中的以下两行: 

#define DEFAULT_SERVER_LIMIT 16 

#define MAX_SERVER_LIMIT 20000

需要注意的是,如果显式声明了ServerLimit,那么它乘以ThreadsPerChild的值必须大于等于MaxClients,而且MaxClients必须是ThreadsPerChild的整数倍,否则Apache将会自动调节到一个相应值(可能是个非期望值)。

估算参数的例子(作个参考,不一定适合我们的情况):

Apache缺省的最大用户数是256个:这个配置对于服务器内存还是256M左右的时代是一个非常好的缺省设置,但随着内存成本的急剧下降,现在大型站点的服务器内存配置一般比当时要高一个数量级不止。所以256个进程的硬限制对于一台1G内存的机器来说是太浪费了,而且Apache的软上限 max_client是受限于HARD_SERVER_LIMIT的,因此如果WEB服务器内存大于256M,都应该调高Apache的 HARD_SERVER_LIMIT。根据个人的经验:2560已经可以满足大部分小于2G内存的服务器的容量规划了

 

一个apache + mod_php的服务器:一个apache进程一般需要4M内存

因此在一个1G内存的机器上:apache_max_process_with_good_perfermance < (1g / 4m) * 2 = 500

apache_max_process = 500 * 1.5 = 750

所以规划你的应用让服务尽量跑在500个进程以下以保持比较高的效率,并设置Apache的软上限在800个。

例子2:

一个apache + mod_resin的服务器: 一个apache进程一般需要2M内存

在一个2G内存的机器上: 

apache_max_process_with_good_perfermance < (2g / 2m ) * 2 = 2000

apache_max_process = 2000 * 1.5 = 3000

--prefix=/another_driver/apache/:建议将apache服务安装在另外一个驱动设备上的目的在于硬盘往往是一个系统使用寿命最低的设备,因此:将服务数据和操作系统完全分开,不仅能提高了数据的访问速度,更重要的,大大方便系统升级,应用备份和恢复过程。

--shared-module=max:使用这种动态加载方式载入子模块会带来5%的性能下降.但给标准化安装和维护带来的好处也远比这多。我们的应用比较固定建议使用静态的。

grep -v "#" httpd.conf.default >httpd.conf

#最大服务进程数:根据服务容量预测设置

MaxClients 256 => 800

其他apache性能优化配置:

HostnameLookups off

On会带来延迟,因为对每一个请求都需要作一次DNS查询。

Options FollowSymLinks

为了得到最佳性能,并放弃对符号连接的保护,可以在需要的地方都设置FollowSymLinks, 而放弃使用SymLinksIfOwnerMatch.

AllowOverride None

如果URL空间允许覆盖(通常是用.htaccess文件), 则Apache会试图对每一个文件名组成部分打开.htaccess.

DirectoryIndex index.cgi  index.pl  index.shtml  index.html

其中最常用的应该放在前面. 不要用通配符而使用完整的列表.

EnableMMAP off

在Apache 2.0需要搜索被发送文件的内容时,比如处理服务器端包含时, 如果OS支持某种形式的mmap(2),则会对此文件执行内存映射。

在某些平台上,内存映射可以提高性能,但是在某些情况下, 内存映射会降低性能甚至影响到httpd的稳定性.我们这个应用则关闭对发送文件的内存映射比较合适。

mod_status 和 ExtendedStatus Off

如果Apache在编译时包含了mod_status, 而且在运行时设置了ExtendedStatus On,则, 对每个请求Apache都会调用两次gettimeofday(2) (或者根据操作系统的不同,调用times(2)), 以及(pre-1.3)几个额外的time(2)调用,使状态记录带有时间标志。 为了得到最佳性能,可以设置ExtendedStatus off (这也是默认的).

调整 TCP 连接切断参数

   在 /etc/sysctl.conf 中加入:

   net.inet.tcp.msl=2000

   net.inet.tcp.always_keepalive=0

   

   上述设置将防止TCP连接默认以Keep Alive方式建立,并避免大量的空闲连接消耗OS

资源;此外,TCP TIME_WAIT的等待时间也从60秒减少到4秒。

 调整 UFS dirhash 允许的内存用量

   vfs.ufs.dirhash_maxmem=67108864 (此设置在5.3p14中已经自动包括)

   

   这一设置将OS默认值提高32倍。

 在 Apache 配置中禁用 KeepAlive:

   编辑 /usr/local/etc/apache2/httpd.conf,将

      KeepAlive On

   改为

      KeepAlive Off

在负载较大的服务器上,上述设置将把同时联到 httpd 上的连接从大约2200降低到400

以下。并有效改善响应时间。此前(大约3周)已经在部分机器上应用了上述设置,目前

为止基本可以确认这些设置不会造成可以为用户所感知的不良影响,同时会改善服务的

响应时间,因此建议在线的全部系统均应用上述设置。

具体技术细节

目前在线上的 FreeBSD 5.3 版本(无论patchlevel)的SINAMAIL内核中均联入了

ACCF_HTTP,其作用是在来自客户的HTTP请求完成之后再将其发给应用程序,从而降低

由于客户端网络较慢导致httpd过早开始等待连接所造成的资源消耗。

禁用KeepAlive之后,客户端在请求多个资源时,将有更大机会发出并发的请求。从

而,由于链路发生丢包等问题而发生的延迟对于下载其他资源的影响将会削弱。缩短

TCP分片超时之后,等待连接关闭的时间将缩短,并使建立的连接更趋稳定。

默认的dirhash最大内存为2MB。目前在生产系统上获得的实际用量通常在16-20MB左

右。将其扩大将改善同一目录下的文件的访问性能。

 

简单性能测试:(建议对配置各种参数分别测试,找出最佳优化参数)

用apache自己带的ab,进行测试的方法,如需要自己测试下就可以了。

[yangbin1@vHost-RH9 apache]$ ./bin/ab -n 10000 -c 100  http://10.210.128.189:7981/

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.121.2.8 $> apache-2.0

Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/

Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/

Benchmarking 10.210.128.189 (be patient)

Completed 1000 requests

Completed 2000 requests

Completed 3000 requests

Completed 4000 requests

Completed 5000 requests

Completed 6000 requests

Completed 7000 requests

Completed 8000 requests

Completed 9000 requests

Finished 10000 requests

 

Server Software:        Apache/2.0.49

Server Hostname:        10.210.128.189

Server Port:            7981

Document Path:          /

Document Length:        1456 bytes

Concurrency Level:      100

Time taken for tests:   20.756253 seconds

Complete requests:      10000

Failed requests:        0

Write errors:           0

Total transferred:      19192048 bytes

HTML transferred:       14653184 bytes

Requests per second:    481.78 [#/sec] (mean)

Time per request:       207.563 [ms] (mean)

Time per request:       2.076 [ms] (mean, across all concurrent requests)

Transfer rate:          902.96 [Kbytes/sec] received

Connection Times (ms)

              min  mean[+/-sd] median   max

Connect:        0   78  60.7     99     554

Processing:    20  125  57.8    114    1149

Waiting:        5  111  53.2    104     869

Total:         47  204  84.4    214    1303

Percentage of the requests served within a certain time (ms)

  50%    214

  66%    218

  75%    220

  80%    223

  90%    264

  95%    302

  98%    447

  99%    530

 100%   1303 (longest request)

测试结果分析:暂时没有。