PHP5-FPM 随机开始消耗大量 CPU

Posted

技术标签:

【中文标题】PHP5-FPM 随机开始消耗大量 CPU【英文标题】:PHP5-FPM randomly starts consuming a lot of CPU 【发布时间】:2012-11-23 19:43:51 【问题描述】:

我遇到了一个非常奇怪的问题,我不确定如何进一步调试。我有一个 nginx + php5-FPM + APC Amazon Ubuntu 实例,上面安装了一个网站,这是一个复杂的 PHP 框架。在尝试调试问题时,我将流程简化为:包含许多大类,创建主要对象,启动会话,从 memcached 检索配置数组,从 memcached 检索 XML 文件,html包含模板,输出被发送到客户端。

然后我使用http_load工具将网站置于每秒20个请求的负载下:http_load -timeout 10 -rate 20 -fetches 10000 ./urls.txt

接下来发生的事情相当奇怪。 top 显示了一堆 php5-fpm 进程,每个进程都占用了几个 % 的 CPU 并且一切运行顺利,如下所示:

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
28440 www-data 20 0 67352 10m 5372 S 4.3 1.8 0:20.33 php5-fpm
28431 www-data 20 0 67608 10m 5304 S 3.3 1.8 0:16.77 php5-fpm
28444 www-data 20 0 67352 10m 5372 S 3.3 1.8 0:17.17 php5-fpm
28445 www-data 20 0 67352 10m 5372 S 3.0 1.8 0:16.83 php5-fpm
28422 www-data 20 0 67608 10m 5292 S 2.3 1.8 0:18.99 php5-fpm
28424 www-data 20 0 67352 10m 5368 S 2.0 1.8 0:16.59 php5-fpm
28438 www-data 20 0 67608 10m 5304 S 2.0 1.8 0:17.91 php5-fpm
28439 www-data 20 0 67608 10m 5304 S 2.0 1.8 0:23.34 php5-fpm
28423 www-data 20 0 67608 10m 5292 S 1.7 1.8 0:20.02 php5-fpm
28430 www-data 20 0 67608 10m 5300 S 1.7 1.8 0:15.77 php5-fpm
28433 www-data 20 0 67352 10m 5372 S 1.7 1.8 0:17.08 php5-fpm
28434 www-data 20 0 67608 10m 5292 S 1.7 1.8 0:18.56 php5-fpm
20648 memcache 20 0 51568 8192 708 S 1.3 1.3 2:51.06 memcached
28420 www-data 20 0 69876 13m 6300 S 1.3 2.3 0:20.89 php5-fpm
28421 www-data 20 0 67608 10m 5300 S 1.3 1.8 0:21.19 php5-fpm
28429 www-data 20 0 9524 2260 992 S 1.3 0.4 0:11.68 nginx
28435 www-data 20 0 67608 10m 5304 S 1.3 1.8 0:18.58 php5-fpm
28437 www-data 20 0 67352 10m 5372 S 1.3 1.8 0:17.87 php5-fpm
28441 www-data 20 0 67608 10m 5292 S 1.3 1.8 0:20.75 php5-fpm

然后经过一段时间(可能在一秒到几分钟之间),几个(通常是两个)php5-fpm 进程突然消耗了所有 CPU:

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
28436 www-data 20 0 67608 10m 5304 R 48.5 1.8 0:23.68 php5-fpm
28548 www-data 20 0 67608 10m 5276 R 45.2 1.7 0:07.62 php5-fpm
28434 www-data 20 0 67608 10m 5292 R 2.0 1.8 0:23.28 php5-fpm
28439 www-data 20 0 67608 10m 5304 R 2.0 1.8 0:26.63 php5-fpm

此时一切都卡住了,所有新的 HTTP 请求都超时。如果我停止 http_load 工具,php5-fpm 会挂在那里很多分钟。有趣的是,如果我执行php5-fpm stop,php5-fpm 进程将消失,但任何使用文件系统的命令都会在执行时出现问题。例如。如果我尝试通过 ssh 下载文件,top 将显示以下内容,需要几分钟才能启动实际下载:

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3298 sshd 20 0 7032 876 416 R 75.2 0.1 0:04.52 sshd
3297 sshd 20 0 7032 876 416 R 24.9 0.1 0:04.49 sshd

PHP 错误日志通常有这样的:

[05-Dec-2012 20:31:39] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 0 idle, and 58 total children
[05-Dec-2012 20:32:08] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 16 children, there are 0 idle, and 66 total children

Nginx 错误日志充斥着这些条目:

2012/12/05 20:31:36 [error] 4800#0: *5559 connect() to unix:/dev/shm/php-fpm-www.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: ..., server: ec2-....compute-1.amazonaws.com, request: "GET /usa/index.php?page=contact_us HTTP/1.0", upstream: "fastcgi://unix:/dev/shm/php-fpm-www.sock:", host: "ec2-....compute-1.amazonaws.com"

PHP-FPM 慢日志没有显示任何有趣的东西,交换从未发生过,我也没有设法收集任何其他关于该问题的有趣事实。我经历了多次配置文件更改,最近的一次是

nginx.conf:http://pastebin.com/uaD56hJF

pool.d/www.conf:http://pastebin.com/mFeeUULC

===更新 1===

站点配置:http://pastebin.com/qvinVNhB

===更新 2===

也刚刚发现dmesg报这样的错误

[6483131.164331] php5-fpm[28687]: segfault at b6ec8ff4 ip b78c3c32 sp bff551f0 error 4 in ld-2.13.so[b78b5000+1c000]

===更新 3===

我们有一个新的 Amazon EC2 微型实例以防万一,以排除可能的硬件问题。另外我现在使用 php-fastcgi 来排除可能的 fpm 错误。其他差异很小,我认为唯一改变的是 Ubuntu->Debian。除了现在服务器设法在 max_execution_time 秒后稍微恢复(然后再次达到峰值)之外,仍然会发生相同的问题。

我尝试使用单独的 test.php,但我不确定这是否是同一个问题,但至少在 top 中看起来是一样的。我创建了一个 test.php 并包含了一堆属于我们框架的库。除了定义类或包含定义类的其他库之外,这些库不做任何事情。我与 APC 进行了核对,所有这些都由它成功提供。我开始以每秒 200 个请求向 test.php 施压,一段时间后同样的事情发生了。除了现在我设法得到一些错误,说“打开的文件太多”。但它并不总是发生,有时它只是开始超时而没有输出错误,并且一些 php 进程卡住了所有 CPU。我只玩了一点,但我认为这里有一个相关性——通过控制包含的库的数量或稍微改变请求/秒的速率,我可以控制 CPU 峰值何时发生。我增加了相关的操作系统变量,但问题仍然存在,尽管它需要更长的时间才能发生(另请注意,我已将限制设置为比我在测试期间执行的请求总数大 N 倍的值)。

fs.file-max = 70000
...
*       soft    nofile   10000
*       hard    nofile  30000
...
worker_rlimit_nofile 10000;
...
(reloaded all the configs and made sure the new system vars actually took affect)

所以到目前为止我能想到的下一个最好的也是唯一的解释是,即使 APC 应该从内存中提取文件,但在内部它的实现方式仍然是在调用 PHP include-s 时仍然使用文件描述符.或者因为它延迟释放它们,或者在某个不幸的时刻太多请求同时到达,系统运行我们的描述符并且新到达的 HTTP 请求很快堆积到一个巨大的队列中。我会尝试以某种方式对此进行测试。

【问题讨论】:

你能发布网站本身的 nginx 配置吗? (不是你的主要配置) 好的,这里是:pastebin.com/qvinVNhB 遇到了同样的问题。就我而言,问题是 PHP72-FPM 在非索引表上进行了大量的数据库查询。就我而言,代码编写不正确。如果问题与 mysql 相关,则有关如何搜索解决方案的更多信息应使用此选项:log_queries_not_using_indexes = ON 【参考方案1】:

我已经运行一个具有类似配置的网站好几个月了,停机时间为零。我看了一下你的配置,感觉还可以。话虽这么说,我很久以前就做了配置。

我会考虑将pm.max_requests = 10000 减少为更合理的形式,例如pm.max_requests = 500。这只是意味着“不要将每个实例用于超过 X 个请求”。这个数字最好不要太高,因为这样做可以让您对可能的 PHP 引擎错误有弹性。

我认为真正的问题很可能出在您的 PHP 脚本中。不知道就很难说。

编辑: 考虑取消注释 ;request_terminate_timeout = 0 并将其设置为类似于 request_terminate_timeout = 20 的内容。然后,您的脚本将需要在 20 秒内完成。您很可能会看到行为发生变化,但我认为您的网站可能会继续存在。这将表明 PHP 脚本错误。

EDIT2:我自己的 php-fpm 配置如下:

[example.com]
listen = /var/run/sockets/example.com.socket
user = www-data
group = www-data
pm = dynamic
pm.start_servers = 5
pm.max_children = 15
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500
php_flag[expose_php] = off
php_flag[short_open_tag] = on

EDIT3:我在你的 nginx 配置中发现了一些意想不到的东西,但它可能什么都没有。

您正在使用fastcgi_ignore_client_abort on;,这会导致旧版本 nginx 下的工作进程出现问题。我自己没有看到这个问题,因为我正在运行最新版本的自定义编译。 nginx网站上的问题描述如下:

在 1.0.2 中,POST 请求在以下情况下无法正确处理 fastcgi_ignore_client_abort 设置为 on 可以导致工作人员 进程段错误。将 fastcgi_ignore_client_abort 切换回 默认(关闭)应该可以解决这个问题。

【讨论】:

感谢您的回复! pm.max_requests 是我经常使用的配置之一,尝试了 200 到 10000 之间的许多 vales。不幸的是,我没有注意到任何变化。我已经将request_terminate_timeout 设置为 10,也没有注意到任何变化。一旦它卡在 100%,我就停止了http_load,等了几分钟让它平静下来,然后不得不关闭 PHP5-FPM,因为它一直在消耗 CPU。 @Eugene 我相当确定的一件事是问题不在于 nginx 方面,但如果您提供特定于站点的配置,我会检查它。稍后,我将把我的工作 php-fpm 配置放在你的比较。它看起来与您所拥有的相似。如果您在那里看到什么,请告诉我。 非常感谢,我会尝试使用您的配置值,并让您知道它是如何进行的。在这一点上,我开始怀疑一些更基本的问题,比如 HDD 问题或一些奇怪的操作系统级配置,这些配置会强制执行一些文件系统锁定,但遗憾的是我缺乏这方面的知识来正确调试此类问题(我确实尝试过,但没有找到任何此类问题的指标)。 这个答案被接受但没有解释。这是否意味着第三个建议解决了问题? @Rathinam,有很多情况会导致您的 PHP cpu 使用率达到最大值,并且很可能与您的 fpm 配置以外的因素有关。不幸的是,我目前无法帮助您进一步诊断问题。我建议您发布自己的新问题,以提高其在社区中的知名度。最良好的祝愿。【参考方案2】:

简单的技巧,但非常有用,可以将处理器使用率降低多达 50%,只需编辑您的 php-fpm 配置:

pm = dynamic

并将其更改为:

pm = ondemand

【讨论】:

这个选项在我的/usr/local/etc/php/7.1/php-fpm.d/www.conf 中.. Mac - Homebrew【参考方案3】:

我的服务器上 PHP-FPM 的行为和你一样。瓶颈肯定在某个地方。 问题变成了:如何在 Nginx - PHP-FPM - Mysql 上找到瓶颈? 最快的查找方法是:Enable Slowlog for PHP-FPM。 将下面的行添加到您的 php-fpm.conf 池中,并确保路径存在

request_slowlog_timeout = 10
slowlog = /var/log/php-fpm/slow.$pool.log

通过阅读日志回溯,您可以找出 PHP-FPM 为何花费如此多的 CPU 或超时。这是我的案例:

[28-Dec-2018 14:56:55]  [pool laravel] pid 19061
script_filename = /public_html/index.php
[0x00007efdda4d8100] hasChildren() /public_html/laravel/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php:75
[0x00007ffe31cd9e40] hasChildren() unknown:0
[0x00007ffe31cda200] next() unknown:0
[0x00007ffe31cda540] next() unknown:0
[0x00007ffe31cda880] next() unknown:0
[0x00007efdda4d7fa8] gc() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Session/FileSessionHandler.php:91
[0x00007efdda4d7e50] gc() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Session/Middleware.php:159
[0x00007efdda4d7d48] collectGarbage() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Session/Middleware.php:128
[0x00007efdda4d7c20] closeSession() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Session/Middleware.php:79
[0x00007efdda4d7ac8] handle() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Cookie/Queue.php:47
[0x00007efdda4d7930] handle() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Cookie/Guard.php:51
[0x00007efdda4d7818] handle() /public_html/laravel/vendor/stack/builder/src/Stack/StackedHttpKernel.php:23
[0x00007efdda4d76e0] handle() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:641
[0x00007efdda4d7598] run() 
/public_html/index.php:51

回溯提到了这些关键字:

"cookie" "session" "collectGarbage()" "laravel"

我一直在搜索和 TADA,Laravel 使用 RANDOM 方法清除过期会话。在我的配置中,PHP 使用 SSD 来处理 Session。 当会话数变得“非常大”这使得 PHP 花费更多时间来处理 => 高 CPU 使用率。

我们可以有很多种瓶颈, 当我们“调试”它时我们就可以知道它。

好好调查一下。

【讨论】:

【参考方案4】:

我现在也遇到了同样的问题,想向你指出这篇文章:

How to determine which script is being executed in PHP-FPM process

它必须是您的 PHP 脚本之一。看看你能不能把失控的进程 ID 和阻碍你的 .php 脚本文件联系起来。

有趣的是,这是在一个速度无可挑剔的服务器上。我认为 WordPress 升级(插件或核心)可能非常负责任。

【讨论】:

哦,不管怎样,升级到最新的 PHP 解决了我的问题。我不得不在 Ubuntu 中更改为比 LTS 更新的更新的存储库。【参考方案5】:

我遇到了同样的问题。我尝试重新配置 PHP-FPM 和 NGINX 并没有走得太远。我们的一个人禁用了 v8js.php (http://php.net/manual/en/book.v8js.php),它解决了这个问题。我建议在找到麻烦制造者之前禁用任何 php 模块。希望这对某人有所帮助。

【讨论】:

以上是关于PHP5-FPM 随机开始消耗大量 CPU的主要内容,如果未能解决你的问题,请参考以下文章

NSRunLoop 正在消耗大量的 cpu 和内存

SQL Server 2014下Database Mail Engine进程消耗大量CPU资源

rmi.transport.tcp.tcptransport Connectionhandler 消耗大量 CPU

nexus 消耗大量cpu资源,启动一堆僵尸进程

如果是MySQL引起的CPU消耗过大,如何优化?

面试官:如果MySQL引起CPU消耗过大,你会怎么优化?