【问题标题】:Multiple queue listeners will run the same job over multiple processes多个队列侦听器将在多个进程上运行相同的作业
【发布时间】:2014-11-10 01:06:30
【问题描述】:

我有一个使用 Laravel 4.2 框架编写的简单 Web 应用程序。我已经配置了 Laravel 队列组件以将新的队列项添加到本地运行的 beastalkd 服务器。

本质上,有一个 POST 路由可以将一个项目添加到 beanstalkd 管中。

然后我将 supervisord 设置为将 artisan queue:listen 作为三个独立的进程运行。我看到的问题是,不同的queue:listen 进程最终会为一个插入的作业生成一到三个queue:worker 进程。

最终结果是插入队列中的一项作业有时会被多个工作人员同时处理,这显然是我试图避免的。

作业代码比较简单:

<?php

use App\Repositories\URLRepository;

class ProcessDataJob {
    private $urls;

    public function __construct(URLRepository $urls)
    {
        $this->urls = $urls;
    }

    public function fire($job, $data)
    {
        $input = $data['post'];

        if (!isset($data['post']) && !is_array($data['post'])) {
            Log::error('[Job #'.$job->getJobId().'] $input was empty inside CreateAuditJob. Deleting job. Quitting. Bye!');
            $job->delete();
            return false;
        }

        //
        // ... code that will take a few hours to run.
        //

        $job->delete();
        Log::info('[Job #'.$job->getJobId().'] ProcessDataJob was successful, deleting the job!');
        return true;
    }
}

有趣的部分是大多数(重复的)队列工作人员在删除作业时会失败,并且错误日志中还剩下这个:

exception 'Pheanstalk_Exception_ServerException' with message 'Job 3248 NOT_FOUND: does not exist or is not reserved by client'

ttr(运行时间)设置为 172,800 秒(或 48 小时),远大于完成作业所需的时间。

【问题讨论】:

    标签: php laravel beanstalkd


    【解决方案1】:

    排队时的作业 time_to_run 是多少?如果运行作业的时间超过 time_to_run 秒,则作业会自动重新排队,并有资格由下一个工作人员运行。

    保留的作业有 time_to_run 秒被删除、释放或触摸。调用touch() 会重新启动超时计时器,因此工作人员可以使用它来给自己更多的时间来完成。或者排队时使用足够大的值。

    我发现 beanstalkd 协议文档很有帮助 https://github.com/kr/beanstalkd/blob/master/doc/protocol.md

    【讨论】:

    • 好的,简单的解决方案就这么多。日志是否显示重复作业都同时开始?还是他们交错了?应用程序某处可能存在超时。否则,您可能必须深入研究调度代码以追踪它在做什么。我写过排队系统(两个用 php,第三个用 beanstalk),但不知道 laravel。
    • 重复作业通常在 10 秒内开始。应用程序内部似乎没有超时,尤其是使用 beanstalk 连接。没有抛出异常或错误。我想这可能是一个豆茎虫。
    • 10 秒太长了……真奇怪。你能检测调度吗?只是为了记录 beanstalk reserve() 返回的作业 ID?对分搜索,将其缩小到 beanstalk 或应用程序。对于超时,我正在考虑一个内置的“10 分钟后声明错误”配置的最大运行时间类型的东西
    • 啊,没有设置超时。在两个单独的连接上运行 reserve 的 beanstalk 服务器的 telnet 返回相同的数据,所以我相当确定这是 beanstalkd 的问题。
    • yikes 什么版本的 beanstalk?
    【解决方案2】:

    由于您使用 Laravel 运行,请验证您的 queue.php 配置文件。

    ttr 值从 60(默认)更改为更适合您的值。

        'beanstalkd' => array(
            'driver' => 'beanstalkd',
            'host'   => 'localhost',
            'queue'  => 'default',
            'ttr'    => 600, //Example
        ),
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-08
      • 1970-01-01
      • 2016-12-31
      • 2013-09-24
      • 2017-10-29
      • 1970-01-01
      • 1970-01-01
      • 2011-08-18
      相关资源
      最近更新 更多