3

我会尽量具体说明这一点——这并不容易,所以请尽量遵循。

我们有一个在 NGINX 上使用 PHP 运行的脚本 - PHP-fpm FastCGI。该脚本从试图访问它的用户那里获取信息,并实时运行一些算法。它不能是在后台运行的计划进程。有时,页面加载甚至需要 5-12 秒 -这没关系。通常,我们会从用户那里收集数据,并向第三方服务器发出多次请求,收集数据并对其进行分析,然后为用户返回响应。

问题是,有很多用户在运行这个脚本,并且服务器变得非常繁忙——因为他们都是服务器上的活动连接,等待响应。我们有 2 台服务器在 1 个负载均衡器下运行,但这还不够。有时服务器一次有超过 1,500 个活动连接。您可以想象这些服务器在该时间范围内如何响应。

我正在寻找解决方案。我们可以向 LB 添加越来越多的服务器,但它是唯一的解决方案,这听起来很荒谬。我们运行了该脚本并将其优化到最大,我可以向您保证 - 该脚本的长时间运行没有真正的解决方案,因为它依赖于需要时间来响应我们实时流量的第 3 方服务器.

有没有您能想到的解决方案,以保持此脚本原样 - 但以某种方式降低这些活动连接对整体服务器功能的影响?有时,他们只是停下来回应。

非常感谢您的阅读!

4

3 回答 3

3

3个月大的问题,我知道,但我忍不住想:

  1. 如果您确定对第三方服务器的所有请求的网络工作总和加上 PHP 脚本中响应的相应处理低于您的硬件限制。

  2. 然后,您的 PHP 脚本可能会低效地忙循环,直到所有响应都从第三方服务器返回

如果我正在处理这样的问题,我会这样做:

  1. 停止使用您自定义的外部 C++ curl 东西,因为 PHP 脚本无论如何都在忙着等待它。

  2. 谷歌并阅读 PHP 的 curl-multi 实现的非忙循环使用

希望这是有道理的。

于 2012-11-04T19:54:50.723 回答
1

我的建议是为请求设置有限的超时时间,并对每个第三方请求使用异步请求。

例如,对于您的页面,您必须显示 5 个第三方请求的结果。这意味着,您调用的内部脚本cURLfile_get_contents5 次,但脚本会因第三方的每次超时而冻结。一步步。这意味着,如果对于每个请求,您必须等待 10 秒的响应 - 您总共将有 50 秒。
User calls the script -> script wait to end -> server is loaded for 50 seconds

现在,如果对第三方的每个请求都将异步发送 - 它会将脚本的加载时间减少到最大请求延迟。因此,您将拥有一些较小的脚本,它们的寿命会更短——并且它会减少服务器上的负载。
User calls the script -> script is loaded -> requests are sent -> there are no scripts that are waiting for the response and consuming resources of your server

愿 AJAX 与您同在!;)

于 2012-08-05T15:17:31.333 回答
1

这是一个非常古老的问题,但由于我有类似的问题,我可以分享我的解决方案。长时间运行的脚本会影响系统的各个部分,并在网络服务器(在活动连接中)、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 实例并将慢速脚本的所有请求发送到该新实例。这允许您在运行时间过多的情况下离散地失败这些请求。这将使您有能力做两件重要的事情:

  • 控制用于慢速脚本的资源量
  • 意味着所有其他脚本永远不会被慢速脚本阻塞,并且(假设操作系统限制足够高)永远不会受到资源限制的影响。

希望对在负载下苦苦挣扎的人有所帮助!

于 2019-04-11T15:13:45.773 回答