【问题标题】:Using multiple variable concurrent Laravel Queues使用多个变量并发 Laravel 队列
【发布时间】:2020-04-21 02:37:16
【问题描述】:

我的用例:

我的应用程序将有任意数量的用户,每个用户都有他们想要处理的各种作业。这些工作应该能够同时发生——无论如何,其中一些工作。

因此,例如,如果 User1 通过 UpdateStock 和 CompleteSale 之类的命令发送,而 User2 通过 UpdateStock 之类的命令发送,则这些命令中的每一个都需要排队并允许彼此同时运行。

我一直在研究Laravel Queues,看起来,如果我将所有 3 个作业放入一个队列中,它们一次只能运行一个,但如果我将它们放入 3 个不同的队列中,它们' d 都可以同时运行。 我理解的对吗?

那么这就引出了我的下一个问题:我需要一个队列,每个用户,每个命令。但是当然,新用户一直在注册,如果我需要运行php artisan queue:listen --queue=user1:command1 & php artisan queue:listen --queue=user1:command2 & php artisan queue:listen --queue=user2:command1 ... 来让它工作,那么......这怎么可能?什么时候可以随时添加新用户...

我的意思是我可以编写一些 php,在每次向队列中添加某些内容后以编程方式执行 php artisan queue:listen --queue=userx:commandx,但我不确定这是否有意义。如果该命令已经运行了怎么办——它会有 2 个进程试图处理同一个队列吗?

也许我想错了。我对整件事感到有点失落。我可以参考一些建议。

【问题讨论】:

    标签: laravel queue


    【解决方案1】:

    回答第一点:是的,如果你有 3 个队列,每个队列都会同时处理,前提是每个队列都有 Queue 工作人员监听。

    至于场景的其余部分,听起来需要另一种方法

    一个队列,每个用户,每个命令

    听起来有点矫枉过正!

    根据我的经验,我建议使用一些队列,例如“低”、“默认”和“高”优先级队列,优先级较高的队列有更多的工作人员(并且可能等待更短的时间)。如果您在 linux 环境中运行,您可以使用诸如 supervisor 之类的程序来配置这些。

    [program:high-priority-worker]
    process_name=%(program_name)s_%(process_num)02d
    command=php /var/www/app/artisan queue:work redis --sleep=3 --tries=3 --queue=high
    autostart=true
    autorestart=true
    user=user
    startsecs=0
    numprocs=8
    redirect_stderr=true
    stdout_logfile=/var/log/www/app/worker.log
    
    [program:default-priority-worker]
    process_name=%(program_name)s_%(process_num)02d
    command=php /var/www/app/artisan queue:work redis --sleep=3 --tries=3
    autostart=true
    autorestart=true
    user=user
    startsecs=0
    numprocs=4
    redirect_stderr=true
    stdout_logfile=/var/log/www/app/worker.log
    
    [program:low-priority-worker]
    process_name=%(program_name)s_%(process_num)02d
    command=php /var/www/app/artisan queue:work redis --sleep=3 --tries=3 --queue=low
    autostart=true
    autorestart=true
    user=user
    startsecs=0
    numprocs=2
    redirect_stderr=true
    stdout_logfile=/var/log/www/app/worker.log
    

    如果您担心确保按顺序执行一系列作业,您可能还想研究作业链 (https://laravel.com/docs/6.x/queues#job-chaining)

    【讨论】:

    • 这么快的问题:假设我设置了主管并将我的high 队列设置为具有numprocs=8——这是否意味着如果我将 8 个作业添加到“高”队列中,他们将 (或者可以)全部同时处理?因为它们都发生在专用于该队列的 8 个进程之一中?
    • 另外,在您的中间工作人员上,您没有指定队列——这是否意味着只处理未指定队列或指定默认队列的已注册作业,并且它不会t 处理指定另一个队列的作业?
    • 所以 laravel 中的第一个队列被称为“default”并且被设置为默认值,你可以根据需要指定,但由你决定。至于进程,主管将为高优先级队列生成 8 个工作人员,每个工作人员每 3 秒轮询一次队列。这意味着您将在“高”队列中拥有多达 8 个作业的并发吞吐量。当一个作业被拾取时,它应该被拾取它的工作人员锁定,但这是在早期版本的 Laravel 中的一个问题。
    • 这是 Sholt 的绝妙建议,我可能最终会走这条路。我认为我唯一的并发路由是(a)无数队列,或者(b)使用 Guzzle 异步请求并尝试真正聪明地使用它们,但这看起来可能比我想到的所有其他选项都更好。
    • 我将暂时搁置这个问题,但我怀疑我会得到比这更有用的答案。我会在几个小时内将此标记为正确。
    【解决方案2】:

    如果我将所有 3 个作业放入一个队列中,它们只会在 一次,但如果我将它们放入 3 个不同的队列中,它们都可以 同时运行。我理解的对吗?

    是的,如果您只有一个队列,作业将依次排列。

    您在这里真正谈论的是缩放

    我认为大多数人会这样做的方式是有足够的队列。然后能够扩大规模。您自己提出的建议(为每个新用户启动队列)也是一种选择。 为同一个队列设置多个侦听器会给您带来问题。几年前我错误地这样做了,并且这些作业可能没有被“锁定”,这意味着同一个作业会被执行多次。

    Laravel Horizon 为您带来平衡选项,这意味着您可以让新工作进入空闲队列。因此,您不必为每个用户指定一个队列。

    如果您需要完全并发(作业必须在准确同一时间开始),那么这种意义上的平衡可能是不够的。

    虽然让多个队列更新相同的库存编号听起来有点冒险。我可以想到一些数据库锁定问题和可能的竞争条件。

    为了给您更具体的建议,我需要了解为什么在您的案例/示例中每个用户需要一个队列。

    【讨论】:

    • To give you a more specific recommendations I would need to understand why you need one queue per user in your case/example. -- 想法是这样的:这些工作都是为了更新和从亚马逊、Ebay 和 Shopify 等 API 获取数据。这些 api 中的每一个都用他们的 api 实现了一个“漏桶”——我可以立即进行 40 次调用,但之后每半秒只能调用一次——所以我的每个客户都有一个唯一的桶,所以 User1 和 User2 以及 User。 ..N 在技术上可以同时向亚马逊提出请求。
    • 所以我什至可以为每个用户、每个频道创建一个队列——一个用于 User1Amazon、User2Amazon、User1Ebay、User2Ebay 的队列——或者每个用户每个作业类型的队列——User1UpdateStock、User2UpdateStock、User1UpdateOrder、 User2UpdateOrder
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 2017-05-18
    • 2020-07-21
    • 2017-05-10
    • 2019-03-21
    相关资源
    最近更新 更多