Apache Tuning

小弟最近管理某单位的伺服器群,最近遇到了连线数的瓶颈,很多时候网页的回应是慢得可以,或是直接停止回应,后来进入系统观察时发现 CPU 和 Memory 也没有达到巅峰,因此决定动手调整 Apache。

加入 mpm worker 模组

Apache 2.0 许多功能和改进,编译时要开启 worker mpm 模组,否则为了和 Apache 1.3 相容会自动选择 prefork 模式。如下图所示,红色的 --with-mpm=worker 是重要的参数值。mpm_worker Module 是 Apache 2 一个重要的模组之一,它设定了 Apache 执行绪的效能,包含了子行程和执行绪的数量,可以参考 mpm_worker.c 的内容。

steven $ ./configure --prefix=/usr/local/httpd --enable-isapi --enable-file-cache --enable-echo --disable-charset-lite --enable-charset-lite --enable-cache --enable-disk-cache --enable-mem-cache --enable-example --enable-case-filter --enable-case-filter-in --enable-dumpio --enable-auth-ldap --enable-ext-filter --enable-deflate --enable-log-forensic --enable-logio --enable-mime-magic --enable-headers --enable-proxy --enable-proxy-connect --enable-proxy-ftp --enable-proxy-http --enable-ssl --enable-optional-hook-export --enable-optional-hook-import --enable-optional-fn-import --enable-http --enable-cgi --enable-cgid --enable-speling --enable-rewrite --enable-so --with-suexec-uidmin --with-suexec-gidmin --with-suexec-logfile --with-suexec-safepath --enable-static-htpasswd --enable-static-htdigest --enable-static-rotatelogs --enable-static-logresolve --with-mpm=worker

让你的机器发挥到极致

在一个高等级的硬体设备下(Intel 64 位元 CPU x 2、2G RAM),以下的设定在同一时间可以处理 5000 个连线(其实还可以容许更多)。

root # vi /usr/local/httpd/conf/extra/httpd-mpm.conf
-------------------------------------------------------
<IfModule mpm_worker_module>
# Apache 启动时先开启 3 个 Threads
StartServers 3
MaxClients 5000
# 最大的连线数
ServerLimit 50
MinSpareThreads 50
MaxSpareThreads 200
ThreadLimit 200
ThreadsPerChild 100
MaxRequestsPerChild 200
</IfModule>
-------------------------------------------------------
root #

广 告

关於 mpm worker 的设定技巧,可以参考 Apache 手册。

减少不必的等待

当然,为了效能,我建议关闭 DNS 的查寻和提高 MaxKeepAliveRequests 的选项并且把 Timeout 值调低。

root # vi /usr/local/httpd/conf/extra/httpd-default.conf
-------------------------------------------------------
# 连线超过 60 秒失败就重试
Timeout 60
# 开启 KeepAlive
KeepAlive On
# 设定同一时间可容许的 KeppAlive 量
MaxKeepAliveRequests 5000
# KeepAlive 多久要自动 Timeout 掉
KeepAliveTimeout 3
# 关掉那费时的 DNS 查寻
HostnameLookups Off
-------------------------------------------------------
root #

连线设定需要考量到很多因素,在早期大部份的网路使用者频宽都不够大,所以一旦你设定太短的 Timeout 值就有可能会马上让使用者需要再次重新连线。但是现今网路使用者大部份以 ADSL 上网,所以等待时间应该不用这么的久。

小弟所调整这些情况,其客户端大部份为学术单位、政府单位,所以对这些大频宽的使用者,太久的 Timeout 值有可能会变成一种不必要的资源浪费。

note: 为什么 Timeout 值要缩短,在一个大流量的网路服务(良好的硬体设备,高频宽的网路速度)在同一时间是需要能够服务更多的使用者,如果 Timeout 太高,那么在连线占满时下一个连线请求就要等到有连线结束掉才能够被服务;相反的若设定太低那么就要常常重新连线。不过重新连线一般的使用者并不会有太大的感觉(TCP/IP 的三向交握很快),所以不要让伺服器一直在等待没有请求的连线。

当一个连线被建立之后,使用者很有可能会在短时间之内又提出新的请求,所以为了避免再次的连线,就会在本次要求结束后,保持连线 KeepAliveTimeout 秒,若是超过了 KeepAliveTimeout 秒,其 Timeout 就会转交给连线逾时,也就是 Timeout 秒之后,会自动断掉连线。

让你的 Apache 更靠近 CPU

在一台设备良好的伺服器上,上面如果只有一项服务的话,那么就应该把大部份的资源都留给它,比方说 Web 服务。
在 Linux 上,根据启动时加以调整 nice 值也可以让 Apache 的处理速度快一点。
nice 的调整范围是在 -20 ~ +19 之间,如果不设定的设所有服务都是在 0。nice 的关念,就是它的值越低,就离 CPU 越近,那么就跟容易取得 CPU 的资源,相反的在正数越高(+1 ~ +19)越不容易得到回应。

启动 apache 时就把 nice 值调到 -10

root # nice -10 /usr/local/httpd/bin/apachectl start &

如果系统已经在启动的话,可以使用 renice 来重新设定其 nice 值。
找出 apache 的 PID,并重新设定

root # netstat -ntulp | grep httpd
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 19249/httpd
root # renice -10 19249


当你调整完毕之后,可以使用 top 指令查看 NI 栏位的变化。

取消不必要的服务

把不要必要的服务全部都关掉以便适出更多的可用资源让 Apache 使用,当系统安装时,大部份的系统建置者通常会把所有的套件都装上去,以免未来要使用的功能不齐全,当然这是我们无法阻止的,但是我们却可以控制系统的服务。
如果你使用 Redhat/Fedora 系统 Linux OS 的话,可以使用 chkconfig 来看看系统启动时到底有那些服务被开启。

root $ chkconfig --list
~ 以上略 ~
rawdevices 0:off 1:off 2:off 3:off 4:on 5:on 6:off
acpid 0:off 1:off 2:off 3:on 4:on 5:on 6:off
ipchains 0:off 1:off 2:on 3:off 4:on 5:on 6:off
iptables 0:off 1:off 2:on 3:off 4:on 5:on 6:off
crond 0:off 1:off 2:on 3:on 4:on 5:on 6:off
anacron 0:off 1:off 2:on 3:off 4:off 5:off 6:off
lpd 0:off 1:off 2:on 3:off 4:on 5:off 6:off
xfs 0:off 1:off 2:on 3:off 4:on 5:on 6:off
ntpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
portmap 0:off 1:off 2:off 3:off 4:on 5:on 6:off
xinetd 0:off 1:off 2:off 3:on 4:on 5:on 6:off
autofs 0:off 1:off 2:off 3:off 4:on 5:on 6:off
nfs 0:off 1:off 2:off 3:off 4:off 5:off 6:off
nfslock 0:off 1:off 2:off 3:off 4:on 5:off 6:off
identd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
~ 以下略 ~
root #

使用 chkconfig 可以看到各服务在系统那个 system level 时会被关闭或开启。
如果你的机器只有单纯的服务网页服务,那么就不应该要有 NFS、telnet、ldap、samba、lpd、cups、mysql 或会占用大量记忆体及 CPU 资源的程式,尤其是像资料库服务。

以下示范如何把 MySQL 在开机时不启动。

root # chkconfig mysqld off

如果 MySQL 正在执行,要把它关闭的话。

root # service mysqld stop

root # /etc/init.d/mysqld stop

重新编译 Apache!

如果你对於系统厂商所附的套件不满意,或是想要转到新版本的 Apache 时,那么就要编译一下 Apache,在编译时可能需要注意一些事项:

不要把所有的模组都编上去

如果一开始就决定要使用 JSP 开发程式,那么就不需要把 PHP 模组都套进来;若不需要使用到 LDAP 认证,那也不需要把 LDAP 的模组也一起编进来,总之,在编译你的 Apache 之前,那么就应该要先确认环境状况而不是一头脑的全都加进去。

确认你的 GCC 版本

说真的,小弟对於程式并不是很熟,所以无法明确的指出 GCC 版本对於编译出来的程式有什么样的结果。不过可以证实的是,有些新版本的 GCC 在编译时,可以让程式更小执行更快。

调校时应该注意的事项

当你开始动手调整之前,应该要考虑主机的能力,比方说在记忆体只有 256 MB 的主机要去服务上千个连线这似乎有点勉强,你应该要注意所设定的数值不会超过主机所能负荷的能力,比方说吃掉 90% 的记忆体,那么到时候可能会得到反效果。

在转换 Apache 版本之前,最好是可以在一台测伺主机上编译一次,若有问题时可以有时间解决,否则一旦在正式上线的主机上做这种实验又没有备份的情况下,可能会有无法预期的结果出现。

正式在执行你的新 Apache 之后,你应该要特别注意系统的负荷、主机资源的使用、效能是否如预期。如果结果不是在预期之内,应该要试者再做更细微的调整,请仔细阅读 Apache 网站上的手册,有时候一些小小的调整可以达到不错的效果 :) 。

参考资料

这篇文章是小弟在工作时实战的心得,因此会有很多疏忽的地方,如果有错也请大家不吝指教。

以下为一些参考资料:

01/20/2007


首页