我在一台 512MB 内存的 VPS 上使用 CentOS 5。我发现 httpd 经常耗尽内存,导致整个系统运行缓慢。但我找不到原因。
当我用top
它来监控进程时,有时其中一个进程httpd
会占用 90% 以上的内存,然后 SSH 会挂起几秒钟。当top
再次刷新时,它httpd
已被内核杀死。几分钟后,这个问题又会重复出现。
这是系统日志:http://pastebin.com/bszy9ahq
我的 Apache prefork 配置:
<IfModule prefork.c>
StartServers 1
MinSpareServers 3
MaxSpareServers 7
ServerLimit 128
MaxClients 128
MaxRequestsPerChild 4000
</IfModule>
这是httpd -V
:
Server version: Apache/2.2.3
Server built: Mar 24 2012 13:32:42
Server's Module Magic Number: 20051115:3
Server loaded: APR 1.2.7, APR-Util 1.2.7
Compiled using: APR 1.2.7, APR-Util 1.2.7
Architecture: 32-bit
Server MPM: Prefork
threaded: no
forked: yes (variable process count)
Server compiled with....
-D APACHE_MPM_DIR="server/mpm/prefork"
-D APR_HAS_SENDFILE
-D APR_HAS_MMAP
-D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
-D APR_USE_SYSVSEM_SERIALIZE
-D APR_USE_PTHREAD_SERIALIZE
-D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
-D APR_HAS_OTHER_CHILD
-D AP_HAVE_RELIABLE_PIPED_LOGS
-D DYNAMIC_MODULE_LIMIT=128
-D HTTPD_ROOT="/etc/httpd"
-D SUEXEC_BIN="/usr/sbin/suexec"
-D DEFAULT_PIDLOG="run/httpd.pid"
-D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
-D DEFAULT_LOCKFILE="logs/accept.lock"
-D DEFAULT_ERRORLOG="logs/error_log"
-D AP_TYPES_CONFIG_FILE="conf/mime.types"
-D SERVER_CONFIG_FILE="conf/httpd.conf"
有什么方法可以知道哪个脚本导致了内存问题,或者只是与 Apache 有关?以及如何解决...
答案1
系统内存不足,并决定终止 apache 以腾出空间。占用所有内存的不一定是 apache。512Mb 对于 128 个 httpd 进程来说可能比较紧张 - 但这个数字可能会有很大差异。您是否查看过 httpd 实例使用了多少内存?不要费心尝试从静态快照中计算出来 - 将内存使用情况(减去缓冲区和缓存)与 httpd 实例数作图,然后进行最小二乘回归 - 斜率是每个实例使用的内存量。然后找出关闭 Apache 时系统使用了多少内存。根据从磁盘读取的内容量,您应该争取至少有 ~20% 的内存可用于缓存/缓冲区。
您是否调整了 httpd.conf?删除了所有冗余模块?应启用 Keepalive,但超时时间最多为 2 秒。启用静态内容的输出压缩和缓存。
如果您怀疑 Apache 存在内存泄漏,请尝试减少 MaxRequestsPerChild。
有时其中一个 httpd 会占用 90% 以上的内存
这更表明存在失控脚本/模块。
有什么方法可以知道什么脚本
从您提供的信息来看,没有找到任何信息 - 没有任何东西告诉我们您使用的是什么脚本语言,也没有告诉我们如何从 httpd 调用它。如果是 PHP,请尝试添加一个 autoprepend 脚本,例如...
<?php
register_shutdown_function('logmem');
function logmem()
{
apache_note('x-php-peak-mem', memory_get_peak_usage());
}
并在您的访问日志中报告该值:
"%{x-php-peak-mem}n"
显然,这只会报告成功完成的请求 - 但这是一个开始。
同样,如果是 PHP,那么将内存限制设置得太高(尽管这也适用于其他 OO 语言)可能会因抑制垃圾收集而适得其反。
(顺便说一句,如果几分钟后内存不足,那么“StartServers 1”就太愚蠢了)
答案2
要解决此问题:
- 你的配置还一样吗?
- 访客数量还一样吗?
- 有任何脚本或者模块被改变吗?
如果您的网站相当繁忙,那么 512 MB 对 Apache 来说不算多。您可能需要调整一下您的配置。