这是一个非常古老的问题,但由于我有类似的问题,我可以分享我的解决方案。长时间运行的脚本会影响系统的各个部分,并在网络服务器(在活动连接中)、php-fpm 和 mysql/其他数据库中造成压力。这些往往会导致一些连锁反应,例如其他请求开始失败。
首先确保您在服务器上安装了 netdata ( https://github.com/netdata/netdata )。如果您正在运行许多实例,您可能会发现设置 Grafana/Prometheus 也是值得的。
接下来确保它可以看到 PHP FPM 进程、Mysql 和 Nginx。Netdata 展示了很多东西,但对于这个问题,我的关键指标是:
- Connections (mysql_local.connections) - 是充满连接的数据库
- PHP-FPM 活动连接 (phpfpm_local.connections) - PHP 是否跟不上
- PHP-FPM 请求持续时间 (phpfpm_local.request_duration) - 处理时间到了吗?
- 磁盘使用时间 (disk_util.sda) - 这显示磁盘是否跟不上(100% = 负载不佳)
- 用户打开文件 (users.files)
确保您有足够的文件句柄 ( https://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/ ),并且磁盘没有被完全占用。这两个都会阻止你让东西正常工作,所以在麻烦的服务器上让它们变大。
接下来检查 Nginx 在 nginx.conf 中有足够的资源:
worker_processes auto;
worker_rlimit_nofile 30000;
events {
worker_connections 768;
}
这将使您有时间找出问题所在。
接下来看php-fpm(/etc/php/7.2/fpm/pool.d/www.conf):
- 将 pm.max_spare_servers 设置为高,例如 100
- 设置 pm.max_requests = 500 - 以防万一您的脚本无法正确释放自身。
然后观看。对我来说,问题是每个请求都会阻止传入连接。对同一脚本的更多请求将阻止更多连接。机器可以正常运行,但是执行 curl 命中的单个慢速脚本或慢速 SQL 语句将在其整个持续时间内占用该连接,因此 30 秒 = 减少 1 个 php 进程来处理传入请求。最终你达到了 500,然后你就用完了。如果您可以增加 FPM 进程的数量,以使慢速脚本请求的频率与它们运行的秒数相匹配。因此,如果脚本需要 2 秒,并且每秒被命中 2 次,那么您将需要一个恒定的 4 个额外的 fpm 工作线程,它们什么都不做。
如果你能做到这一点,那就停下来——除此之外的额外努力可能不值得。如果它仍然觉得这将是一个问题 - 在盒子上创建第二个 php-fpm 实例并将慢速脚本的所有请求发送到该新实例。这允许您在运行时间过多的情况下离散地失败这些请求。这将使您有能力做两件重要的事情:
- 控制用于慢速脚本的资源量
- 意味着所有其他脚本永远不会被慢速脚本阻塞,并且(假设操作系统限制足够高)永远不会受到资源限制的影响。
希望对在负载下苦苦挣扎的人有所帮助!