![周一至周五,PHP 的 CPU 容量达到 100%,并且会占用大量内存](https://linux22.com/image/588425/%E5%91%A8%E4%B8%80%E8%87%B3%E5%91%A8%E4%BA%94%EF%BC%8CPHP%20%E7%9A%84%20CPU%20%E5%AE%B9%E9%87%8F%E8%BE%BE%E5%88%B0%20100%25%EF%BC%8C%E5%B9%B6%E4%B8%94%E4%BC%9A%E5%8D%A0%E7%94%A8%E5%A4%A7%E9%87%8F%E5%86%85%E5%AD%98.png)
我们在英国运营一个面向小学的学习平台,一切运行良好。然而,周一至周五下午 4 点左右,我们发现同样的问题出现了——1-2 个 PHP 线程的 CPU 使用率会达到 100%,并逐渐开始消耗内存,直到服务器崩溃。
98% 以上的请求都是 HTTPS,这些请求进入我们的第 7 层负载均衡器,然后该负载均衡器解密 SSL 数据、添加标X-HTTP-Forwarded-For
头并将数据转发到端口 80 上的应用服务器(目前我们有 2 个这样的服务器)。我们的应用服务器在端口 80 上有 Varnish,它接收来自负载均衡器的请求并将请求传递到端口 81 上的 Nginx。然后 Nginx 确定需要使用哪个“vhost”,并将任何 PHP 处理传递到正在监听套接字(通过 spawn-fcgi 管理)的 PHP-CGI。还有一个 Memcached 实例正在运行,MySQL 在单独的服务器/从属设置上运行。
一整天中,两个应用服务器上的负载通常不会超过 0.8,然而在下午 4 点左右,问题出现了。我设法运行了strace
一些导致问题的实际线程,并且总是看到同样的事情:
stat("/usr/share/zoneinfo/Europe/London", {st_mode=S_IFREG|0644,st_size=3661, ...}) = 0
stat("/usr/share/zoneinfo/Europe/London", {st_mode=S_IFREG|0644,st_size=3661, ...}) = 0
这个过程会无限重复,直到你用 SEGKILL 或 oomkiller 杀死该进程,才会停止。当时没有计划运行的 cron 任务,而且我也没有办法确切地看到与正在运行的 PHP 进程相关的 Nginx 请求。
我们运行的是 PHP 5.3.14,上周我们从 5.3.8 升级到了 5.3.14,以排除旧版本的问题。这个问题已经持续了几个月,我们不知道是什么原因造成的。我们非常频繁地部署软件,因此很难追踪可能导致问题的特定版本 - 尤其是我们不知道这个问题首次发生的日期。Varnish 是 3.0.1 版,Nginx 是 1.0.6 版(据我所知,现在已经有一年了),我们的服务器运行的是 CentOS 5.7 版(最终版),它们有 3.07Ghz 的 Intel i3 540 和 8GB 的 RAM。
Debian 邮件列表中有一个关于类似问题的讨论,你可以找到这里。
以前有人见过类似的事情吗?有人有什么想法或建议吗?有没有办法将 Nginx 请求直接链接到 PHP 线程?有没有更好的方法可以查看 PHP 进程正在做什么?(我已经看到提到 GDB,但我必须重新编译 PHP)
谢谢!
答案1
我找到了问题所在,是 Internet Explorer。我们的 CSS 中有一个对 .htc 文件的错误引用,出于某种原因,该文件被发送到 PHP 进行处理。PHP 不知道如何处理 .htc 文件,最终变得疯狂并消耗了服务器上所有可用的资源。
答案2
有了评论中的额外信息,我认为我们可以放心地假设问题发生在负载高峰期间 - 在线用户数量每日峰值。没有固定的确切时间,有时会在其他时间发生,而其他日子则有效地排除了 cron 作业占用资源之类的问题。
这可能听起来很疯狂,但首先要增加 MySQL 最大连接数限制 - 我见过当超出连接数限制时,以 FCGI 运行的 PHP 会发生奇怪的事情,这与您遇到的问题没有什么不同。