php-fpm: ERROR: [pool ] no free scoreboard slot

php-fpm: ERROR: [pool ] no free scoreboard slot

最近我的 php 应用程序经常不可用。一天发生好几次。

在 php-fpm 错误日志中,我看到了这些消息:

[23-Mar-2015 16:49:42] NOTICE: fpm is running, pid 8038
[23-Mar-2015 16:49:43] NOTICE: ready to handle connections
[23-Mar-2015 16:49:47] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 98 idle, and 105 total children
[23-Mar-2015 16:49:57] WARNING: [pool www] child 8132 exited on signal 11 (SIGSEGV) after 13.640528 seconds from start
[23-Mar-2015 16:49:57] NOTICE: [pool www] child 8151 started
[23-Mar-2015 16:49:59] WARNING: [pool www] child 8091 exited on signal 11 (SIGSEGV) after 16.331350 seconds from start
[23-Mar-2015 16:49:59] NOTICE: [pool www] child 8155 started

[24-Mar-2015 09:38:01] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there are 0 idle, and 15 total children
[24-Mar-2015 09:38:01] ERROR: [pool ] no free scoreboard slot

[24-Mar-2015 17:00:39] NOTICE: [pool www] child 27622 started
[24-Mar-2015 17:00:51] WARNING: [pool www] child 27482 exited on signal 11 (SIGSEGV) after 230.000581 seconds from start
[24-Mar-2015 17:00:51] NOTICE: [pool www] child 27623 started
[24-Mar-2015 17:01:07] WARNING: [pool www] child 27522 exited on signal 11 (SIGSEGV) after 246.737464 seconds from start
[24-Mar-2015 17:01:07] ERROR: [pool ] no free scoreboard slot
[24-Mar-2015 17:01:13] WARNING: [pool www] child 27538 exited on signal 11 (SIGSEGV) after 252.268165 seconds from start
[24-Mar-2015 17:01:13] ERROR: [pool ] no free scoreboard slot

执行service php-fpm reload暂时解决了问题,过一段时间又出现了。

根据nginx的访问日志,每分钟最多1000个请求,大约有600个请求传递给php-fpm(其他都是静态文件)。好像不重。

服务器环境:

php-fpm配置:

pm = dynamic
pm.max_children = 100
pm.start_servers = 100
pm.min_spare_servers = 100
pm.max_spare_servers = 1000
pm.max_requests = 500

我试过 pm = static 并更改了其他参数,但都没有用。

作为临时解决方案,我编写了一个shell 脚本来定期检查服务可用性。如果不可用,请重新加载 php-fpm.

但是怎样才能彻底解决问题呢?

在我修改了一行试图从 MySQL.

中获取 table 的所有记录(有时高达 10K)的糟糕代码后,问题终于消失了

我检查了 nginx 的访问日志,惊讶地发现许多对 api 的请求产生了 500 个响应代码。

经过一番挖掘,我发现这是由一行代码造成的,该代码试图从 MySQL 中获取 table 的所有记录。记录不多的时候还好,但是超过10K条记录时,请求以500 internal error结束。

修改糟糕的代码后,不再请求那个api yield 500,php-fpm 错误也消失了。

2015-12-28更新:

我认为破坏整个应用程序的真正原因是对执行不当的 api 的请求占用太多内存,需要太多执行时间。

因此,php-fpm worker pool 中充满了此类请求,因此没有worker 来处理其他请求。所以整个应用程序崩溃了。

这些请求以 500 失败的原因可能是内存 运行 耗尽,或者执行时间超过 php.ini 中指定的 max_execution_time

如果你运行遇到这个问题,检查你的访问日志(nginx或php-fpm),并尝试找出总是占用太多的请求memory/time(内存用法只能在php-fpm的访问日志中找到),或者总是失败的请求。然后检查问题是否是由那些请求引起的。