【问题标题】:Laravel Queue - How to setup a FAST processorLaravel 队列 - 如何设置 FAST 处理器
【发布时间】:2018-04-21 13:36:06
【问题描述】:

我正在使用 Laravel 5.5,并且正在尝试设置一些快速队列处理。我遇到了一个又一个的障碍。

本网站是一个雇主/雇员匹配服务。因此,当雇主发布工作职位时,它需要遍历我们系统中的所有员工并计算一些变量以确定他们与工作的匹配程度。我们已经把这一切都弄清楚了,但是当系统中有数千名员工时,一次处理一个需要很长时间。所以,我准备写几个表。第一个是定义职位 ID 和状态的简单表。第二个是列出所有员工 ID、职位 ID 和正在处理的员工状态的表格。只需几秒钟即可编写,然后允许用户在应用程序中继续前进。

然后我有另一个服务器设置,每分钟运行一个 cron 来检查第一个表中的新条目。找到后,它会将其标记为已启动,然后抓取所有员工并遍历每个员工并在 Laravel 中开始排队的工作。我定义的作业确实正确提交到队列并运行queue:work 实际上确实正确处理了作业。这一切都经过测试。

但是,我遇到的问题是我已经尝试了数据库 (MySQL)、Redis 和 SQS 用于队列,它们都非常慢。我正在使用同一台服务器尝试操作queue:work(使用Supervisor并尝试运行多达300个进程),但随后创建了3个不运行cron但只运行Supervisor(每个克隆100个进程)的克隆并被杀死第一台服务器上的主管。使用数据库它会处理得很好,虽然运行 10k 个排队的作业需要几个小时,但是使用 SQS 和 Redis 我会遇到很多失败。脚本花费的时间太长或其他什么。我检查了运行 worker 的克隆上的 CPU,它们几乎没有达到 40%,所以我没有对服务器过度征税。

我刚刚阅读了有关 Horizo​​n 的信息,但我不确定它是否有助于解决这种情况。我一直在尝试查找有关如何使用 Laravel 正确设置队列处理系统的信息,但遇到的问题多于答案。

有没有人熟悉这些东西并对如何正确设置它有任何建议,以便它非常快速且无故障(假设我的代码没有错误)?

更新:根据其他一些帖子建议,我想我会分享更多细节:

  1. 我使用 Forge 作为设置工具,它带有 2G RAM 的 AWS EC2 服务器。
  2. 三个克隆中的每一个都具有以下工作器配置:

    command=php /home/forge/default/artisan queue:work sqs --sleep=10 --daemon --quiet --timeout=30 --tries=3  
    
    process_name=%(program_name)s_%(process_num)02d  
    autostart=true  
    autorestart=true  
    stopasgroup=true  
    killasgroup=true  
    user=forge  
    numprocs=100  
    stdout_logfile=/home/forge/.forge/worker-149257.log
    
  3. 数据库在 Amazon RDS 上。

我很好奇 Laravel 缓存是否可以与队列系统一起使用。排队脚本的元素对于每次运行都是通用的,所以如果我从一开始就将这些数据排队,它可能会节省一些时间。但我不相信这会是一个巨大的进步。

【问题讨论】:

  • 通过查看问题描述和复杂性,我建议您将问题发布到 larachat slack 团队。如果您找到了答案,请在此处发布。
  • 我在 Laravel 中没有这样做的经验,但几年前我们有一个 PHP 项目在工作,它使用 beanstalkd 作为消息队列,每小时愉快地执行数百万个任务。如果执行 10.000 个任务需要数小时,可能是您的匹配算法太复杂或性能不够?
  • Andrew,您发现 Redis/SQS 后端有哪些错误?您在 queue:work 上使用 --timeout=30,这意味着作业将在 30 秒后中止。在一个盒子上同时运行一堆繁重的作业(100 似乎有点高),它们可能会超时。

标签: php laravel queue laravel-5.5 laravel-horizon


【解决方案1】:

如果我们忽略每个作业处理的实际逻辑,只考虑运行作业的开销,Laravel 的排队系统可以轻松在环境中每小时处理 10,000 个作业,如果不是几倍的话问题中描述 - 尤其是使用 Redis 后端。

对于典型的队列设置,每个盒子 100 个队列工作进程似乎非常高。除非这些作业在等待状态中花费大量时间——例如通过网络向 Web 服务发出请求并且只使用几毫秒处理响应的作业——否则大量进程同时运行实际上会降低性能。每个处理器内核运行一个以上的工作程序不会让我们获得太多收益。额外的工作人员会产生开销,因为操作系统必须在所有竞争进程之间分配和安排计算时间。

我检查了运行 worker 的克隆上的 CPU,它们几乎没有达到 40%,所以我没有对服务器过度征税。

在不了解项目的情况下,我可以建议,这些工作可能确实花费了 一些 时间等待某事。您可能需要调整工作人员的数量,以找到空闲时间和过度拥挤之间的最佳平衡点。

使用数据库可以正常处理,虽然运行 10k 个排队的作业需要几个小时,但是使用 sqs 和 redis 我会遇到很多故障。

如果您将错误消息和任何其他相关信息添加到问题中,我会尝试更新此答案。

我很好奇 Laravel 缓存是否可以与队列系统一起使用。排队脚本的某些元素对于每次运行都是通用的,所以如果我从一开始就将这些数据排队,可能会节省一些时间。

我们当然可以在队列中执行作业时使用缓存 API。我们看到的任何性能改进都取决于为我们可以存储在缓存中的每个作业复制数据的成本。我不能确定多少缓存会节省时间,因为我不熟悉该项目,但您可以分析工作中的代码部分以查找昂贵的操作。

或者,我们可以将可重用数据缓存在内存中。当我们使用artisan queue:work 初始化队列工作者时,Laravel 会启动一个 PHP 进程并为工作者执行的 所有 作业启动应用程序一次。这不同于典型 PHP Web 应用程序的应用程序生命周期,其中应用程序为 每个请求 重新启动,并在每个请求结束时处理状态。因为每个作业都在同一个进程中执行,所以我们可以创建一个对象,将共享作业数据缓存在进程内存中,也许可以通过将单例绑定到 IoC 容器中,作业可以读取甚至比 Redis 缓存存储快得多,因为我们避免了从缓存后端获取数据所需的开销。

当然,这也意味着我们需要确保我们的作业不会泄漏内存,即使我们没有如上所述缓存数据。

我刚刚阅读了有关 Horizo​​n 的信息,但我不确定它是否会有所帮助。

Horizo​​n 提供了一项监控服务,可能有助于跟踪此设置的问题。如果应用程序使用 Horizo​​n 可以在空闲时分配工作的其他队列,它也可能会稍微提高效率,但问题似乎并不表明是这种情况。

三个克隆中的每一个都具有以下工作器配置:

command=php /home/forge/default/artisan queue:work sqs --sleep=10 --daemon --quiet --timeout=30 --tries=3

(旁注:对于 Laravel 5.3 及更高版本,--daemon 选项已弃用,queue:work 命令默认以守护程序模式运行。)

【讨论】:

    猜你喜欢
    • 2018-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-07
    • 2015-08-08
    • 2013-07-16
    • 2017-10-08
    相关资源
    最近更新 更多