Apache 2.x 是一个通用的 web 服务器,被设计在灵活性,可移植性和性能之间达到平衡。虽然被设计用于一些特殊的基准记录,Apache 2.x 在许多实际应用场景中性能不凡
相比于 Apache 1.3,2.x 包含很多额外的优化来提高吞吐量和性能。这些提高大多数是默认的。然而,有一些编译时和运行时可选的配置能够显著影响性能。一些配置选项能够是 httpd 更好的利用硬件和系统的能力,另一些能够在速度上得到提升
Hardware and Operating System Issues
RAM 是影响 web 服务器最主要的硬件问题。web 服务器是绝对不应该使用交换分区的,因为会增加请求的延迟。这将会造成用户重复刷新页面而增大负载。应该控制
MaxRequestWorkers (服务器同时处理的最大请求数)的设置,那样的话,服务器就不会产生那么多的进程切换。
除此之外,CPU,网卡和硬盘都要足够快,“足够快”需要实验检测
Run-Time Configuration Issues
HostnameLookups and other DNS considerations
Apache 1.3 之前,
HostnameLookups 选项默认是 On。这增加了每个请求的延迟,因为在请求结束之前它要求 DNS 解析完成。在 Apache 1.3 这个设置默认是 Off。如果需要在日志文件中把 IP 地址解析为对应的 hostname,请使用 Apache 自带的
logresolve 程序或其他可用的软件包
建议在其他的机器上做这个日志操作以免影响 web 服务器的性能
如果你使用
Allow from domain 或
Deny
from domain(使用 hostname 或 domain name 而不是 IP 地址) 那么将会有两次 DNS 解析的过程。
所以,为了达到最好的性能,可能的话在这个参数中使用 IP 地址而不是名称
其实也可以将这个选项括起来,例如在 <Location/server-status> 部分。这种情况下,DNS 解析只会匹配的请求中进行。例如下面这个实例会禁用 DNS 解析除了 .html 和 .cgi 文件:
HostnameLookups off <Files ~ "\.(html|cgi)$"> HostnameLookups on </Files>
不过即使如此,如果在某些 CGI 当中确实需要 DNS 名称,可以考虑在需要的 CGI 中发送 gethostbyname 请求
FollowSymLinks and SymLinksIfOwnerMatch
在任何 URL 空间中,如果没有
Options FollowSymLinks 或者有
Options SymLinksIfOwnerMatch ,Apache 将会产生额外的系统调用来检查符号链接。每个文件产生一个额外的系统调用。例如:
DocumentRoot /www/htdocs <Directory /> Options SymLinksIfOwnerMatch</Directory>
如果像这样配置,并且客户端发出这样的请求 URL/index.html。Apache 将会执行 lstat(2) 在 /www,/www/htdocs 和 /www/htdocs/index.html。这些 lstst 结果不会被缓存,所以在每个单独的请求当中都会执行。如果确实希望符号链接安全检查,可以像这样做:
DocumentRoot /www/htdocs <Directory /> Options FollowSymLinks </Directory> <Directory /www/htdocs> Options -FollowSymLinks +SymLinksIfOwnerMatch</Directory>
所以,为了达到最高的性能,而且没有符号链接保护,在任何地方设置 FollowSymLinks,并且禁用 SymLinksIfOwnerMatch
在任何 URL 空间中 allow override(.htaccess 文件)Apache 将会试图为每个文件名部分打开 .htaccess 文件。例如:
DocumentRoot /www/htdocs <Directory /> AllowOverride all </Directory>
如果像这样配置,并且客户端发出这样的请求 URL/index.html。Apache 将会试图打开 /.htaccess,/www/.htaccess 和 /www/htdocs/.htaccess 文件
所以,为了达到最好的性能,使用 AllowOverride None 在系统的任何地方
可能的话,如果非常注重性能可以避免使用内容协商。事实上内容协商带来的好处大于它所造成的性能问题。有一种情况能够加速服务器。相对于使用通配符例如:
使用一个完整的列表:
DirectoryIndex index.cgi index.pl index.shtml index.html
先列出最通用的选项
同时注意,创建一个明确的类型映射文件比使用多视图提供更好的性能,因为必要的信息同能够通过这个文件读取而不用去浏览目录中的文件
Memory-mapping
某些情况下,Apache 2.x 需要查看网页文件的内容 -- 例如,当执行一个 server-side-include 进程 -- 如果系统支持 mmap(2) 通常会出现内存映射
在一些平台上,内存映射能够提高性能。然而,有些情况下内存映射会影响服务器的性能:
在一些系统上,当 CPU 数量增加时,mmap 不如 read(2) 表现的好。在多处理器的 Solaris 服务器上,有时候禁用 mmap Apache 2.x 解析文件更快
如果内存映射一个在 NFS 文件系统上的文件,同时其他机器上的 NFS 客户端正在删除或修改这个文件,下次再访问这个文件内容的时候将返回总线错误
在上面提到的这些情况中,应该使用 EnableMMAP off 来禁用内存映射
Sendfile
某些情况下,Apache 2.x 可以忽略网页文件的内容 -- 例如,当提供静态文件内容 -- 如果系统支持 sendfile(2) 操作,通常会使用内核的 sendfile
在一些平台上,使用 sendfile 能够提高系统的性能,通过消除分离 read 和 send 机制。然而,有些情况下使用 sendfile 会影响 httpd 的稳定性:
某些 build 系统没有检测到的平台可能打破 sendfile 支持,特别是如果二进制文件是从其他平台移植过来的
在挂载了 NFS 的系统,内核可能无法通过它缓存的网络文件提供有效的服务
在上面提到的这些情况中,应该使用 EnableSendfile off 来禁用 sendfile 分发文件内容
one-pre-second 规则的实现是为了避免机器陷入生成子进程的过程中。如果机器一直忙于生成进程那么它就无法处理请求。但是它对 Apache 的性能有严重的影响使得它不得不被替换掉。Apache 1.3 的代码改进了这个规则。它会生成一个,等待一秒,然后生成两个,等待一秒,然后生成四个,等待一秒,直到一秒生成 32 个子进程。当到达
MinSpareServers 指定的数量,无论一秒生成多少个它都会停止
当使用 keep-alive 时,进程会保持打开的连接处于活动状态来接受更多的请求。默认的
KeepAliveTimeout(长连接的时间) 为 5 秒把影响降到最低。在网络带宽和服务资源之间权衡
Compile-Time Configuration Issues
Choosing an MPM
Apache 2.x 支持可插拔的并发模型,叫做
多处理模块(MPM)。当编译安装 Apache 的时候,必须选择使用的 MPM。对于通常的类 Unix 系统,有几个 MPM 可以选择。MPM 的选择会影响 httpd 的速度和规模:
worker MPM 使用多个子进程,每个子进程又有多个线程。每个线程一次处理一个请求。worker 适用于大流量的站点因为它比 prefork 占用更少的内存
event MPM 也是多线程的,但是它被设计允许多个请求同时被处理通过转移进程工作来支持线程,释放主线程来处理新的请求
prefork MPM 使用多个子进程,每个子进程又一个线程。每个进程一次处理一个连接请求。在大多系统上,prefork 的速度和 worker 相近,但是它占用更多的内存。在一些场景下, prefork 的设计比 worker 更有优势:它能够被用于没有线程安全的第三方模块,在线程调试支持不完善的平台上更易调试
Modules
既然内存使用在性能上是一个重要的考虑点,那么应该尽量取消加载不使用的模块