Apache 似乎无法控制它保留多少内存。在 MPM prefork 中,您可以控制要允许的最大进程数,但无论您在那里使用多少,现有进程需要的内存总是有可能超过物理可用内存。如果需要高内存的条件没有改变,OOM 终止程序将开始终止随机 Apache 进程而不解决任何问题,Apache 将继续创建新进程,导致服务器崩溃。所以有两个问题:
Apache 不应该控制它分配多少内存吗?
如果没有更多可用内存,无论 MaxClients 或 ServerLimit 如何,是否有办法阻止 Apache 创建新进程?
如果没有,有人能确认 nginx 是否有同样的风险吗?在我看来,nginx 不会像 apache 那样轻易地触发 OOM-Killer 到崩溃点,因为我读到它有少量正在运行的进程,并且内存消耗或多或少稳定。我不知道的是nginx 是否有能力在内存耗尽后停止创建线程,并将这些请求排队,直到有更多内存为止。
对于那些投票反对该问题的人:研究工作已经完成,但它提出的对问题 1 和 2 的答案正如沃姆布尔的评论:是的对于问题 1,不回答问题 #2。也许这些答案对很多人来说太明显了,但我觉得难以置信,所以我决定在这里问。
答案1
回答您直接提出的问题:
Apache 不应该控制它分配多少内存吗?
是的,应该如此。事实也确实如此。
如果没有更多可用内存,无论 MaxClients 或 ServerLimit 如何,是否有办法阻止 Apache 创建新进程?
不,那里没有。
有人能确认 nginx 是否存在同样的风险吗?
是的,因为它无法阻止 nginx 在内存压力下创建新进程。
下面是一个更广泛的答案,可能对来这里寻求有关该主题信息的人更有用。
内存不是随机消耗的。如果没有泄漏,或者在进程中执行了符合停机问题的子语言,单个 Apache 工作进程使用的内存将受到严格限制。因此,解决您的问题的方法是:
- 了解您的 Apache 进程实际上正在做什么。
- 不要使用有泄漏的模块。
- 不要将完整的编程语言运行时嵌入到您不想因内存消耗而发疯的进程中。
最后一点值得强调:Apache 内存问题几乎完全是由 引起的mod_php
,这在创建时是一个坏主意,而且随着时间的推移变得越来越糟。但问题是,如果你将 PHP 执行移到一个单独的进程,比如使用 php-fpm,那么仍然除非您已设置适当的资源控制(很大程度上,与 Apache 内部的旋钮相同),否则这些进程可能会失控并消耗掉所有 RAM。从内存消耗的角度来看,通过运行 php-fpm 获得的唯一好处是,mod_php
相对于为典型工作负载提供服务所需的 Apache 工作程序数量(在 prefork 中),php-fpm 工作程序数量很少,因此您不会获得大量大型进程,而只会获得少量大型进程。