Apache 内存问题

Apache 内存问题

所以我确信这个问题可能之前已经被问过,但我想确保我得到了正确的信息。

我正在运行一个装有 Debian 5 和 Apache 2.2 的 360 Linode 机器。我自己编译了所有内容(没有使用 apt-get)。时不时地(每隔几周一次?),我的服务器会随机“崩溃”:它会突然达到 100% 的 CPU 使用率(实际上是 400%,但你知道我的意思)并交付机器。您无法通过 SSH 查看问题所在,服务器本身停止接受连接。修复它的唯一方法是重新启动机器。

最近,这种情况开始以相对频率发生:24 小时、12 小时、10 小时、8 小时、6 小时、4 小时。最后,大约两天前,在它锁定之前,我终于看到了一瞥。我注意到磁盘 IO 升高了,几乎没有剩余的 RAM!此外,有大量 httpd 进程以 3-4% 的 RAM 运行。所谓大量,是指当我执行 ps -ef 时,它们占据了整个屏幕。如果向上滚动,它们占据了我 SSH 客户端的整个缓冲区。

因此,我对代码进行了一些调整,认为有些东西没有正确关闭。我修复了 PHP 中的内存问题,打开了更详细的错误日志记录并修复了一堆错误,这似乎在一定程度上有所帮助。崩溃又回到了大约每 24 小时一次。

我确信这是因为内存太少,而我收到的大量请求导致我的服务器进入交换区。由于有太多请求进入交换区,磁盘 IO 急剧上升,导致我的 CPU 使用率急剧上升,导致我的服务器锁定。

以下是我尝试修复它的方法:我做了一些研究,发现我应该使用 prefork。我查看了我的配置,找不到任何 ServerLimit 或 MaxClients 或类似的东西,所以我添加了一些“默认”值,我的服务器拒绝接受任何传入连接。实际上,prefork 值通过切断连接阻止了所有入站 http 流量(可能是因为我的服务器无法处理 prefork?我不知道)。

在我看来,我的服务器“过去”的表现很好,只是所有这些 Apache 进程一直挂起并泄漏内存。有没有办法设置 Apache 进程的超时或限制它们的数量?最好的解决方案是使用 prefork,这似乎很愚蠢;我不得不想象有更好的方法。

多谢你们

答案1

看来您通过惨痛的经历认识到了 PHP 占用大量内存并且可扩展性不强。

以下是一些建议(无特定顺序):

如果您仍然怀疑存在内存泄漏,请将 MaxRequestsPerChild 设置为非常低的值。

考虑购买更多内存,360MB 现在确实不多。

尝试通过运行 ps 或 top 来查找 httpd 进程的平均大小,然后设置 MaxClients,以便所有内容始终适合内存。交换是一种死亡螺旋,处理请求的速度越慢,apache 需要分叉的进程就越多,占用的内存就越多。

如果您将 php 作为模块加载到 apache 中,它将在每个请求中加载,无论是脚本还是静态文件(图像、css、.js 或诸如此类)。考虑从单独的服务器提供静态内容,或使用 fastcgi 或反向代理(如 nginx)让 apache 仅提供 php,以限制您必须在内存中保留的胖 php 实例数量。

答案2

我猜你的机器内存不足,导致机器不稳定。根据我的经验,每个运行的 Apache 进程都有可能占用大量内存。如果你在 Apache 中将 php 作为模块运行,请查看 php.ini 中的值memory_limit =。我有 128M,当你只有 10 个 Apache 进程运行时,这个值相当大。它们可能一开始不会占用那么多内存,但如果你的 PHP 应用程序内存泄漏或确实需要 128M,那么你很容易就会达到服务器的限制。

我的建议是:物理内存除以memory_limit等于max_procs

答案3

如果你的内存真的不够,你可以尝试运行像 lighttpd 或 nginx 这样的程序,并以 php 作为 fastcgi 进程,我没有使用过 nginx,但我经常使用 lighttpd,它的内存/CPU 开销极低。

Lighttpd 和 php 通过 fastcgi 教程

答案4

您是否正在连接任何数据库后端?通常,如果某些查询开始变慢,Apache 进程就会开始备份,并且由于 linode 上的 RAM 数量较少,它会滚雪球般地崩溃,导致 CPU 和负载猛增。

另外,您提到您正在使用工作者模型。如果您 100% 确定您在 PHP 中使用的所有模块都是线程安全的,那么这样做是没问题的。但是实际的 php 安装手册建议不要使用它(php 手册)... 无论您选择哪种型号,您都需要确保正确调整它们。一个好的起点是调整 LAMP 系统。如果 MaxClients 没有正确调整,Apache 最终可能会导致您的系统崩溃,因为它会在您的网站流量激增时占用所有内存。

相关内容