【问题标题】:Apache uses excessive CPUApache 使用过多的 CPU
【发布时间】:2010-09-15 11:36:09
【问题描述】:

我们经营一个中等规模的网站,每天的网页浏览量达到几十万。直到上周末,我们在虚拟机上运行的负载通常低于 0.2。操作系统是 Ubuntu。

在部署最新版本的应用程序时,我们还在部署前进行了 apt-get dist-upgrade。部署后,我们注意到 CPU 上的负载急剧增加(有时达到 10 并停止响应页面请求)。

我们尝试从 PHP 中转储整整一分钟的 Xdebug 分析数据,但仔细查看后发现只有一些速度较慢的部分,但无法解释巨大的跳跃。

我们现在非常确定我们网站的新版本中没有任何东西会引发问题,但我们无法确定。我们已经回滚了很多更改,但问题仍然存在。

在查看进程时,我们发现单个 Apache 进程在比严格必要的更长时间内使用相当多的 CPU。但是,当在受影响的进程上使用 strace 时,我们什么也没看到

accept(3,

在收到新连接之前它会挂起一段时间,所以我们实际上看不到导致问题的原因。

堆栈是 PHP 5、Apache 2(prefork)、MySQL 5.1。大多数事情都是通过 Memcached 运行的。我们已经尝试过 APC 和 eAccelerator。

那么,我们的下一步应该是什么?是否有任何我们忽略/不知道的分析方法?

【问题讨论】:

  • 你是从哪个版本升级到哪个版本的?我的意思是 a) PHP,b) Apache 和 c) memcached。
  • 很遗憾,我没有这方面的日志。据我所知,没有 apt-get/aptitude 日志。

标签: php mysql performance apache


【解决方案1】:

我会使用 dTrace 来解决这个谜团...如果它在 Solaris 或 Mac 上运行...但由于 Linux 没有它,您可能想尝试他们的 Systemtap,但我不能说关于它的可用性的任何信息,因为我没有使用它。

使用 dTrace,您可以在一天内轻松找出罪魁祸首,并希望使用 Systemtap 会类似

【讨论】:

  • Systemtap 现在看起来有点复杂。
【解决方案2】:

答案最终与 Apache 无关。如前所述,我们在虚拟机上。我们的用户会话非常大(想想每个活跃用户 500kB),所以我们有很多磁盘 IO。磁盘快满了,这意味着 Ubuntu 花了很多时间来移动东西(或者我们认为)。没有简单的方法来扩展磁盘(因为它没有为 VMWare 正确设置)。这完全扼杀了性能,Apache 和 MySQL 偶尔会使用 100% CPU(在很短的时间内),并且系统更新 CPU 使用率表的速度非常慢,以至于它似乎卡在了那里。

我们最终设置了一个新的虚拟机(这也让我们有机会彻底记录服务器上的所有内容)。在新 VM 上,我们分配了大量磁盘空间,并将会话移到内存中(使用 memcached)。我们的负载在非高峰使用时下降到 0.2,在接近高峰使用时下降到大约 1(在 2-CPU VM 上)。将会话移到 memcached 会占用大量磁盘 IO(我们经常使用大约 2MB/s 的磁盘 IO,这非常糟糕)。

结论;有时你只需要重新开始...... :)

【讨论】:

    【解决方案3】:

    从您的 Apache 进程中看到 accept() 调用并不少见 - 那是网络服务器在等待新请求。

    首先,您要确定负载的参数是什么。类似的东西

    vmstat 1
    

    将向您展示您的系统在做什么。查看“swap”和“io”列。如果您在 'si' 和 'so' 列中看到除 '0' 以外的任何内容,则您的系统由于内存不足而正在交换。考虑减少正在运行的 Apache 子节点的数量,或者在您的服务器中投入更多的 RAM。

    如果 RAM 不是问题,请查看“cpu”列。您对“us”和“sy”列感兴趣。这些显示您在用户进程或系统中花费的 CPU 时间百分比。较高的“我们”数字将矛头指向 Apache 或您的脚本——或者可能是服务器上的其他东西。

    跑步

    top
    

    将显示哪些进程最活跃。

    您是否排除了您的数据库?我在生产 LAMP 堆栈上看到的意外高负载的最常见原因归结为数据库查询。您可能已经部署了包含昂贵查询的新代码;或者到了数据集中有足够多的行导致以前便宜的查询变得昂贵的地步。

    在高负载期间,做

    echo "show full processlist" | mysql | grep -v Sleep
    

    查看是否有长时间运行的查询,或者同时运行大量相同的查询。其他 mysql 工具将帮助您优化这些。

    您可能会发现为 Apache 配置和使用 mod_status 很有用,它可以让您查看每个 Apache 子节点正在处理的请求以及它已经处理了多长时间。

    最后,设置一些长期的统计监控。像 zabbix 这样的东西配置起来很简单,并且可以让你随着时间的推移监控资源使用情况,这样如果事情变得缓慢,你就有历史基线可以比较,并更好地了解问题开始的时间。

    【讨论】:

    • 问题是 Apache 使用 CPU。内存绰绰有余(升级前我们运行 512MB,现在有 2GB)。没有交换发生。 MySQL 慢查询日志报告没有异常。在大量使用期间,我们现在看到负载峰值达到 40。
    • mod_status 是您从这里开始的最佳选择。此外,要跟踪所有 Apache 进程,而不仅仅是父进程,请尝试: ps aux | grep h[t]tpd | awk '{ 打印 "-p"$2 }' | xargs 跟踪
    【解决方案4】:

    另一个我不能保证对您有任何好处的选择,但值得付出努力。是阅读新版本的详细变更日志,并查看可能会远程影响您的更改。

    浏览变更日志不止一次救了我。尤其是当一些配置选项发生变化并且某些东西被弃用时。最坏的情况是它会给你一些关于下一步看哪里的线索

    【讨论】:

    • 对于这种情况,它并没有真正帮助。我们最初确实这样做了,但发现了一些性能问题,但不幸的是,回滚这些更改并没有解决问题。
    【解决方案5】:

    也许你以前和现在不在哪里使用工人 MPM?

    我知道 PHP5 不适用于 Worker MPM。在我的 Ubuntu 服务器上,PHP5 只能与 Prefork MPM 一起安装。 PHP5 模块似乎与多线程版本的 Apache 不兼容。

    我在这里找到了一个链接,它将向您展示如何使用 mod_fcgid 获得更好的性能

    要查看工人 MPM 是什么,请参阅 here

    【讨论】:

    • 没有想法,恐怕我以为你可能在旧版本的应用程序中使用 php4,现在因为升级到 php5 apapche 正在 prefork 模式下运行。您的旧版本应用程序使用的是 php4 吗?
    • 大概一个月大。我们在每次部署之前都会进行升级。不过,在这个问题之后我们可能会停止这样做...... :)
    猜你喜欢
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多