PHP-FPM在执行繁重工作时拥有太多用户时崩溃

时间:2016-02-10 09:19:56

标签: php mysql apache

我有一台服务器运行Apache / 2.2.22(Debian),PHP 5.6.17作为FPM和MySQL 5.6.25。

该项目使用名为Redaxo的CMS运行(我不认为它很重要,但无论如何我都会告诉你)。在Redaxo中有一些功能需要一些时间(例如删除缓存并重建它需要1-2分钟)。在这个时候,当其他用户进入网站时,FPM崩溃了500 Internal Server Error,我不得不多次重新加载页面,直到服务器错误消失并且过程完成。

我注意到只有在同一时间网站上有太多用户并且只有在繁重的操作完成时才会发生这种情况。

10个用户同时只是冲浪=没问题
10个用户同时只是冲浪,而缓存删除= 500每个人都有错误。

我通过禁止网站为除了我之外的所有人(.htaccess deny / allow with ip)检查了这个。然后我做了沉重的操作,没有问题。只要有多个人再次访问该网站,问题就出现了。

它可能是什么?您需要我提供哪些信息?

php-fpm.conf

中设置了这些值(未注释)
[global]
pid = /run/php5-fpm.pid
error_log = /var/log/php5-fpm.log
emergency_restart_threshold = 0
include=/etc/php5/fpm/pool.d/*.conf

在特定项目fpm.conf

中设置(未注释)这些值
[projectname]
user = projectname
group = projectname

listen = /var/run/php5-fpm-projectname.sock
listen.owner = projectname
listen.group = projectname
listen.mode = 0660

pm = dynamic
pm.max_children = 150
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 30

chdir = /

php_value[upload_max_filesize] = 128M
php_value[max_post_size] = 128M
php_value[max_execution_time] = 180
php_value[memory_limit] = 256M

脚本失败时,如果有帮助,可以使用MySQL和文件创建吗?但它很大,所以我不确定我是否应该在这里发布它?或者如果它甚至是问题?

apache错误日志说明了这个

[Tue Feb 09 10:54:01 2016] [error] [client {IP}] (104)Connection reset by peer: FastCGI: comm with server "/fcgi-bin-php5-fpm-projectnmae" aborted: read failed
[Tue Feb 09 10:54:01 2016] [error] [client {IP}] FastCGI: incomplete headers (0 bytes) received from server "/fcgi-bin-php5-fpm-projectnmae"

或者

[Tue Feb 09 11:00:46 2016] [error] [client {IP}] FastCGI: incomplete headers (0 bytes) received from server "/fcgi-bin-php5-fpm-projectname"
[Tue Feb 09 11:00:48 2016] [error] [client {IP}] (104)Connection reset by peer: FastCGI: comm with server "/fcgi-bin-php5-fpm-projectname" aborted: read failed

fpm-log说明如下。当然总是不同的时间

[10-Feb-2016 09:40:59] WARNING: [pool projectname] child 10970 exited on signal 7 (SIGBUS) after 50.186611 seconds from start
[10-Feb-2016 09:40:59] NOTICE: [pool projectname] child 11092 started

有时会出现这样的警告

[09-Feb-2016 11:00:41] WARNING: [pool projectname] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 0 idle, and 6 total children
[09-Feb-2016 11:00:42] WARNING: [pool projectname] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 16 children, there are 0 idle, and 7 total children

以下是一些调试信息

[18-Feb-2016 17:42:01] WARNING: [pool projectname] child 9088 exited on signal 7 (SIGBUS) after 70.130564 seconds from start
[18-Feb-2016 17:42:01] NOTICE: [pool projectname] child 9205 started
[18-Feb-2016 17:43:55] WARNING: [pool projectname] child 9099 said into stderr: "NOTICE: PHP message: PHP Notice:  Undefined offset: 1181 in /var/www/projectname/htdocs/redaxo/include/classes/class.ooarticle.inc.php on line 44"
[18-Feb-2016 17:43:55] WARNING: [pool projectname] child 9099 said into stderr: "NOTICE: PHP message: PHP Warning:  Invalid argument supplied for foreach() in /var/www/projectname/htdocs/redaxo/include/classes/class.ooredaxo.inc.php on line 134"
[18-Feb-2016 17:43:55] WARNING: [pool projectname] child 9099 exited on signal 7 (SIGBUS) after 183.838886 seconds from start
[18-Feb-2016 17:43:55] NOTICE: [pool projectname] child 9330 started
[18-Feb-2016 17:44:00] WARNING: [pool projectname] child 9101 exited on signal 7 (SIGBUS) after 188.987954 seconds from start
[18-Feb-2016 17:44:00] NOTICE: [pool projectname] child 9336 started

4 个答案:

答案 0 :(得分:2)

这可能只是来自MySQL服务器的某些锁定问题的影响。

您必须在延迟期间连接到MySQL主机。

  • 如果无法连接,那么您的MySQL服务器或用户允许的并发连接数就会用完

  • 如果可以连接,则必须查看mysql命令“show processlist”返回的内容。现在你有两个选择:

    • 许多“等待查询缓存锁定”:这将要求您更改一些MySQL服务器配置。 (这可能是由超大查询缓存引起的)

    • 您有一个请求,它会占用您需要优化的所有资源。

答案 1 :(得分:1)

除非你有足够的RAM可用(比如超过16GB),否则我建议你资源不足,导致500错误。

您的配置是说您可以生成多达150个PHP-FPM进程,每个进程可以使用256MB内存 - 仅此一项就可以使PHP-FPM服务器使用超过38GB的内存,如果没有,它将会导致500错误。

计算每个服务器可以使用的内存,然后正确设置。这个CMS需要高达256MB的内存吗?它可以用更少的内存(如32MB)运行吗?如果MySQL,Apache和Nginx位于同一服务器中,请将每个人使用的内存分开,然后为pm.max_childrenphp_value[memory_limit]设置正确的值。

请注意,缺少资源是系统范围的,因此如果您的PHP进程使用所有可用内存,MySQL可能会因资源耗尽而崩溃(这可能是找不到记录的原因)。 / p>

如果你能说出你有多少内存,我可以帮你配置这些数字。

在发布缓存删除之前知道可用内存量是多少以及在运行时可用内存量也是很好的 - 它可能确实使用了太多内存并使其他进程窒息(如果它使用PHP -CLI,它可能没有内存限制。)

答案 2 :(得分:1)

我一直在关注这几天,最后决定增加2美分。

我已经使用FPM很长一段时间了,这是一件很棒的事情,但是用它来获得可扩展的配置是另一回事。有很多可能会导致你的问题出错,但我有一个怀疑。

我想专注于输出中出现的PHP错误,因为它们表明出现了一些不应该出现的错误。我想知道,当您清除缓存并且用户浏览网站时,他们同时会删除不完整的数据,因为某些信息已被删除或正在重建。您甚至可能会看到正在删除缓存的情况,并且同时缓存了新内容。我没有查看用于缓存删除的CMS代码,但是您显示的PHP错误似乎表明在此过程中正在获取一些无效数据。

尝试的一件事是在删除缓存之前显式锁定表,然后释放它们。这样,用户在删除内容时无法读取或写入数据。在您调用以清除缓存的任何脚本中,尝试添加查询LOCK TABLES articles WRITE, othertable WRITE, anyothertable WRITE。这将阻止其他会话(用户)在清除缓存时读取或更新这些表。

用户不耐烦,如果他们尝试加载页面并且没有给他们任何反馈,他们通常会尝试重新加载,或者返回并点击其他链接。这可能导致FPM进程的数量增加。如果10个用户刷新5次,那么现在有50个额外的进程正在运行,并且还会让事情变得更糟。

- 其他东西

在Apache中增加ProxyTimeout或超时。如果你有一个可以运行一段时间的脚本,如果Apache在一定时间内没有得到任何数据,那么它将终止连接(这可能没问题)。如果需要5分钟来清除缓存并且PHP没有发送任何内容直到它完成,并且Apache的超时时间为120秒,它将在连接完成之前丢弃连接,从而导致超时,就像您看到的那样。我有很多网站可以做多达10分钟的事情,所以我的Apache超时是600秒。这允许PHP请求完成而不会破坏。

我注意到的其他事情是您正在使用unix域套接字进行FPM通信。这可以,但是在非常繁忙的站点上它们不能很好地扩展。我建议改用TCP套接字。 listen = 127.0.0.1:9000然后,您需要修改Apache以使用tcp而不是域套接字进行连接。

设置listen.backlog,以便在忙时可以将连接排队。您可能还需要使用sysctl调整内核值net.core.somaxconn,因为它通常很低。

Apache MPM:如果您尚未使用它,请切换到MPM worker。由于您正在使用FPM,因此worker对于Apache来说是一个非常有效的MPM,比prefork(通常是默认的)要好得多。确保根据需要进行调整(即适当地设置服务器,线程和MaxRequestWorkers)。

- 结束

我认为这里没有太复杂的事情,我要看的第一件事是确保缓存删除可以不间断地完成。即使这意味着用户在几分钟内看到一个维护页面,或者他们的请求在短时间内被阻止,直到它完成,如果它避免了500和错误,那么这是一个很小的代价。

老实说,我认为删除缓存和浏览的人会影响流程,并且需要的时间超过必要时间或中断。

如果您有任何问题或随时与我联系,请与我们联系。

答案 3 :(得分:-1)

每次服务器挂起时,如果php和/或Apache达到限制,您就会看到不同的错误。

如果你的主机是Unix / Linux,你可以在CMS执行任何艰苦的工作时检查命令$ top的结果吗?

如果您看到内存耗尽,交换内存的很大一部分已填满且CPU位于顶部,请尝试调整php.ini的memory_limit以分配资源。但可能你需要增加资源,内存和CPU。

如果内存和CPU不忙,可能是你为php分配了更少的内存。你可以运行更多的php-fpm worker,每个进程的内存限制,...请参阅http://linuxbsdos.com/2015/02/17/how-to-reduce-php-fpm-php5-fpm-ram-usage-by-about-50/。另请参阅Apache内存和CPU配置。