![PHP-FPM + nginx - 池繁忙并针对可能糟糕的 PHP 代码进行优化 - 502 错误](https://linux22.com/image/772229/PHP-FPM%20%2B%20nginx%20-%20%E6%B1%A0%E7%B9%81%E5%BF%99%E5%B9%B6%E9%92%88%E5%AF%B9%E5%8F%AF%E8%83%BD%E7%B3%9F%E7%B3%95%E7%9A%84%20PHP%20%E4%BB%A3%E7%A0%81%E8%BF%9B%E8%A1%8C%E4%BC%98%E5%8C%96%20-%20502%20%E9%94%99%E8%AF%AF.png)
我曾经遇到过这样的情况:即使流量稍微增加,PHP-FPM 也无法正常工作。一段时间以来,我一直在尝试寻找实际原因,但至今没有成功。
它始于特定站点给出 502 错误,查看 PHP-fpm 日志我得到了以下信息:
WARNING: [pool www-userA] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 39 idle, and 49 total children
接下来我检查了服务器资源,top 显示资源利用率几乎为 0,仅为 2-4%。接下来是调整 PHP-FPM 池:
pm = dynamic
pm.max_children = 800
pm.process_idle_timeout = 5s
pm.start_servers = 40
pm.min_spare_servers = 40
pm.max_spare_servers = 80
pm.max_requests = 500
php_admin_value[max_execution_time] = 60
;Added later to troubleshoot further
request_slowlog_timeout = 5s
slowlog = /var/log/pool_userA_fpm_slow_log
;Added later to compensate if there queue issue for troubleshooting
listen.backlog =24000
我几乎读过所有与此主题相关的 PHP-FPM 帖子,其中包括: https://stackoverflow.com/questions/25097179/warning-pool-www-seems-busy-you-may-need-to-increase-pm-start-servers-or-pm
该服务器仅配备 12GB 左右的 RAM 和 8 核处理器,用于 nginx+php-fpm。我的每个 PHP 进程大约为 15-20MB。
尝试增加pm.max_children = 1500
但过了一会儿又看到同样的错误“池很忙”。
然后,我在 php-fpm 中启用了 slowlog,并为 mysql 启用了 slow log。
- 在 php-fpm 慢速日志中,我发现一些 php 页面需要大约 5 秒才能完成,
- 在 mysql 慢日志中,发现一些查询检查了 200-500 万行(大约需要 5 秒才能完成)
假设 PHP 脚本可能会导致排队或积压,因此我listen.backlog =24000
在 /etc/security/limits.conf 中为该特定用户添加了软限制和硬限制,以便为慢速脚本提供空间,
userA soft nofile 4096
userA hard nofile 65536
进一步在 sysctl 中。
echo "net.core.somaxconn=65536" >> /etc/sysctl.conf
进一步在 php-fpm master php-fpm.conf 中添加,即外部池配置:
rlimit_files = 65536
rlimit_core = 0
我的ulimit -Hn
说:
524288
此外,由于 php-fpm 变得繁忙,我发现我可以在 php-fpm 中添加以下指令,以便在繁忙时重新启动,但这并没有发生,我必须手动重新启动 php-fpm 才能让网站再次运行:
[global]
emergency_restart_threshold 10
emergency_restart_interval 1m
process_control_timeout 10s
如上所述,如果 php-fpm.log 中出现池繁忙错误,上述指令不会重新启动
到目前为止,我猜测是因为 PHP 脚本太慢,导致我的 php-fpm 子进程耗尽并导致 502 错误。我无法控制 PHP,因此需要通过调整服务器配置来提供解决方案。
我尝试增加pm.max_children = 2000
,但问题仍然存在。有时会出现504 Gateway Time-out
错误。
另一方面,如果我changed pm = ondemand
我首先收到以下通知:
listen.backlog(25000) was too low for the ondemand process manager. I updated it for you to 65535
后来又出现这个错误,这次又出现 504 错误:
[11-Nov-2021 06:56:45] WARNING: [pool userA] server reached max_children setting (800), consider raising it.
需要注意的是,在所有情况下,服务器几乎没有负载,资源使用率为 2-4%。所以我猜这更多的是配置问题,而不是资源使用问题。
我浏览了 serverfault 上几乎所有与 PHP-FPM 相关的主题,也阅读了大量文档,但仍然一无所获。希望有人能为我指明正确的方向。
谢谢