如何阻止 Apache 使我的整个服务器崩溃?

Vla*_*eev 6 linux memory apache-2.2

我维护了一个包含一些服务的 Gentoo 服务器,包括 Apache。它是相当低端的(2GB 内存和具有 2 个内核的低端 CPU)。我的问题是,尽管我尽了最大的努力,但过载的 Apache 还是会导致整个服务器崩溃。事实上,在这一点上,我几乎确信 Linux 是一个可怕的操作系统,不值得任何人花时间寻找负载下的稳定性。

我尝试过的事情:

  1. 为根 Apache 进程(及其所有子进程)调整 oom_adj。那几乎没有效果。当 Apache 过载时,它会使系统陷入困境,因为系统会在杀死任何东西之前将其他所有东西都调出。
  2. 关闭交换。没有帮助,它会将内存分页卸载到 / 上的进程和其他文件的二进制文件,从而导致相同的效果。
  3. 将其放入内存受限的 cgroup(限制为 512 MB 的 RAM,总数的 1/4)。这“有效”,至少在我自己的压力测试中 - 除了服务器在负载下不断崩溃(基本上停止所有其他进程,无法通过 SSH 访问等)
  4. 以空闲 I/O 优先级运行它。这最终不是一个很好的主意,因为它只会导致系统负载无限期地攀升(达到数千个)而几乎没有明显影响 - 直到您尝试访问磁盘的未缓冲部分。这导致任务冻结。(对于良好的 I/O 调度来说就这么多,嗯?)
  5. 限制与 Apache 的并发连接数。由于大多数插槽被长请求(文件下载)占用,因此将数字设置得太低会导致网站无响应。
  6. 我尝试了各种 Apache MPM,但都没有成功(prefork、event、itk)。
  7. 从 prefork/event+php-cgi+suphp 切换到 itk+mod_php。这提高了性能,但没有解决实际问题。
  8. 切换 I/O 调度程序(cfq 到截止日期)。

只是强调一下:我不在乎 Apache 本身是否在负载下宕机,我只希望系统的其余部分保持稳定。当然,让 Apache 在短暂的密集负载后快速恢复会很棒,但一次一个步骤。

现在,我对人类如何能在这个时代设计一个操作系统而感到震惊(不允许一个系统组件使整个系统崩溃)实际上是不可能的 - 或者至少,非常难做。

请不要建议诸如 VM 或“购买更多 RAM”之类的东西。


在朋友的帮助下收集的更多信息: 当调用 cgroup oom 杀手时,进程挂起。这是调用跟踪:

[<ffffffff8104b94b>] ? prepare_to_wait+0x70/0x7b
[<ffffffff810a9c73>] mem_cgroup_handle_oom+0xdf/0x180
[<ffffffff810a9559>] ? memcg_oom_wake_function+0x0/0x6d
[<ffffffff810aa041>] __mem_cgroup_try_charge+0x32d/0x478
[<ffffffff810aac67>] mem_cgroup_charge_common+0x48/0x73
[<ffffffff81081c98>] ? __lru_cache_add+0x60/0x62
[<ffffffff810aadc3>] mem_cgroup_newpage_charge+0x3b/0x4a
[<ffffffff8108ec38>] handle_mm_fault+0x305/0x8cf
[<ffffffff813c6276>] ? 时间表+0x6ae/0x6fb
[<ffffffff8101f568>] do_page_fault+0x214/0x22b
[<ffffffff813c7e1f>] page_fault+0x1f/0x30

此时,apache memory cgroup 几乎死锁,并且在 syscalls 中烧 CPU(都有上面的调用跟踪)。这似乎是 cgroup 实现中的一个问题......

Ali*_*man 7

我不想这么说,但你似乎问错了问题。

这不是要阻止 Apache 关闭您的服务器,而是要让您的网络服务器每秒提供更多查询 - 足以让您没有问题。重新定义问题的一部分答案是限制 Apache,使其不会在高负载下崩溃。

对于第二部分,Apache 有一些你可以设置的限制——MaxClients是一个重要的配置。这限制了允许运行的孩子数量。如果您可以为长时间运行的进程(例如正在下载的大文件)减轻 Apache 的负载,那么这是 Apache 中能够为 PHP 提供服务的另一个插槽。如果文件下载必须由 PHP 层验证,他们仍然可以这样做,并将静态内容传回更优化的网络服务器,例如使用NginX sendfile

同时,在每次请求中分叉 Apache 以最慢的方式运行 PHP - 作为 CGI(无论您使用什么 apache MPM) - 也让机器花费大量时间不运行您的代码。mod_php 明显更加优化。

当 Apache 和 PHP 层得到适当优化时,PHP 可以处理大量流量。例如,昨天,即 2010 年 12 月 11 日,我运行的这对 PHP 服务器在 24 小时内完成了近 1900 万次点击,其中大部分是在上午 7 点到晚上 8 点的时间段内。

这里还有很多其他问题,以及其他关于优化 Apache 和 PHP 的文章,我认为您需要先阅读它们,然后再指责 Linux/Apache 和 PHP。


ues*_*esp 1

您可以尝试以下一些常规操作:

  • 从你的描述中很难判断 Apache/Linux 是否真的崩溃了或者只是变得严重过载。我怀疑您的服务器负载如此之高,唯一有效的做法就是重新启动电源。除非有实际崩溃的具体证据,否则我会将问题视为过载的服务器。如果您优化了服务器的性能,但它实际上仍然崩溃,那么您可以努力查找并解决该问题。
  • 您通常不希望您的服务器陷入定期进行交换的情况,尤其是任何 Apache 实例。您可能很快就会陷入负载失控的情况,其中服务器运行良好,但当流量增加几个百分点时,它开始使用交换,负载猛增,导致网站速度缓慢或无法访问。为了防止 Apache 使用交换,请减少最大客户端/连接的数量和/或通过禁用任何不需要的模块来减少内存使用。另请参阅下一点。
  • 您提到 Apache 中的连接正在被文件下载等长请求使用。为了帮助减少这个问题,您可以使用第二个 Web 服务器(如 lighttp)设置来仅提供 Apache 转发/重定向请求的静态内容。这可以释放 Apache 中的连接来完成繁重的工作,并让您减少最大客户端/连接的数量。
  • 如果您需要防止 DoS,无论是有意还是无意,您都可以安装和设置各种 Apache 模块。例如,我使用了 mod_evasive 和 mod_limitipconn,它们足以防止恶意程度较低的 DoS 类型。
  • 不要忽视优化 Apache 或操作系统或应用程序的其他部分。计算机非常擅长准确地执行您告诉它们的操作,因此如果您的 Apache 设置显示“使用比该服务器更多的资源”,那么它就会准确地执行该操作。与许多软件一样,Apache 旨在与大量硬件和应用程序良好配合,但需要针对两者进行正确设置。默认配置仅适用于简单、低流量的网站。
  • 通过一些调整,您应该能够找到一个平衡点,即服务器达到高负载但仍然有足够的响应能力来登录和检查它。此时,您的选择是分析和优化应用程序(包括添加缓存层)或获取更好的硬件。此步骤应该在正确设置 Apache 之后进行。