【问题标题】:How to prevent queue system of processing more than one job from a queue at once?如何防止队列系统一次处理一个队列中的多个作业?
【发布时间】:2020-05-19 00:29:06
【问题描述】:

我有很多任务,应该按正确的顺序处理。我想将它们按“类型”划分到不同的队列中。队列应该是动态创建的。然后我想启动 X 工人,它将处理队列中的任务。但是有一个重要的规则——从每个队列中,一次只能处理一个任务。原因是——指定类型的每个任务都可以改变应用程序的状态,所以如果最后一个任务还没有完成,我就无法开始处理相同类型的新任务。

我想将 Laravel 队列系统与 Redis 驱动程序一起使用,但我不确定它是否能够做到这一点。如何防止队列系统一次从每个队列中获取多个作业?有什么想法吗?

提前感谢您的帮助。

【问题讨论】:

    标签: php laravel queue


    【解决方案1】:

    如果您使用的是supervisor,那么这就是您可以在.conf 文件中执行的操作。

    [program:laravel-worker]
    process_name=%(program_name)s_%(process_num)02d
    command=php /var/www/html/****/artisan queue:work
    autostart=true
    autorestart=true
    user=root
    numprocs=1  <----- this is what you are looking for
    redirect_stderr=true
    stdout_logfile=/var/www/html/****/storage/logs/supervisord.log
    

    numprocs 指令将指示 Supervisor 运行 1 个 queue:work 进程并对其进行监控,如果失败则自动重新启动它。 (Laravel Queue Supervisor Doc)

    【讨论】:

    • 但是,当我需要多个工人时,情况如何?例如 – 10 个队列和 5 个工作人员。如果我理解正确,您的解决方案仅适用于一名工人。我可以复制此配置,但不可能有多个工作人员从同一个队列中接受作业吗?
    【解决方案2】:

    作业链允许您指定应在主作业成功执行后按顺序运行的排队作业列表。如果序列中的一个作业失败,则不会运行其余作业。要执行排队作业链,您可以对任何可调度作业使用 withChain 方法。

    如果您想指定应该用于链接作业的默认连接和队列,您可以使用allOnConnection 和allOnQueue 方法。

    ProcessPodcast::withChain([
        new OptimizePodcast,
        new ReleasePodcast
    ])->dispatch()->allOnConnection('redis')->allOnQueue('podcasts');
    

    请参阅Laravel docs 了解更多信息。

    【讨论】:

    • 这不是我的情况。就我而言,每份工作都是一样的。它进行一些计算并更改应用程序的状态。这是一个示例场景 - 任务 A 将应用程序的状态更改为“暂停”。只有当应用程序的状态为“活动”时,B 才会进行一些计算。因此,如果有一个情况,两个工人同时处理来自进程的任务,而任务 B 将在任务 A 完成之前启动,那么一切都会搞砸。
    • @KrzysztofSzala 您希望在作业 A 完成后运行作业 B,对吗?所以答案是工作链,如果不向我展示你的一些代码,我就无法理解你的情况。
    • 好吧,可能我没有解释清楚。作业 A 和作业 B 是相同的作业,但具有不同的有效负载。将其视为用户操作。我们有 StoreUserActionJob,它处理来自队列的消息。第一条消息将状态更改为“已暂停”,因此应用程序应拒绝下一条消息。但如果队列系统同时开始处理两条消息,则第二条消息可能会更早完成。这对我来说是一个不受欢迎的情况。
    猜你喜欢
    • 2017-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-27
    • 1970-01-01
    相关资源
    最近更新 更多