【问题标题】:Laravel Queue generating `illuminate:queue:restart` continuouslyLaravel 队列不断生成`illuminate:queue:restart`
【发布时间】:2020-08-07 10:52:23
【问题描述】:

我的 Laravel 队列正在运行,但在数据库连接上,这是配置:

'database' => [
    'driver' => 'database',
    'connection' => 'mysql',
    'table' => 'jobs',
    'queue' => 'default',
    'retry_after' => 190,
    'block_for' => 0,
]

这就是我运行它的方式:

php artisan queue:work --queue=xyz_queue > storage/logs/queue.log

在 redis CLI 上,这是每秒都在发生的事情:

【问题讨论】:

    标签: laravel redis queue laravel-6


    【解决方案1】:

    这是正常和预期的行为。根据documentation

    由于队列工作者是长期存在的进程,它们不会在不重新启动的情况下获取对代码的更改。因此,使用队列工作者部署应用程序的最简单方法是在部署过程中重新启动工作者。您可以通过发出 queue:restart 命令优雅地重新启动所有工作人员:php artisan queue:restart

    此命令将指示所有队列工作人员在处理完当前作业后优雅地“死亡”,以免丢失现有作业。

    • queue:restart 所做的是将当前时间戳设置为illuminate:queue:restart 键的值。
    • 当队列即将被进程 (php artisan queue:work) 消耗 时,它会从 illuminate:queue:restart 键获取时间戳值,并且在作业即将完成之后strong> 它再次从同一个键中获取值。
    • 比较作业处理前的值与作业处理后的值是否相同。
    • 如果不同,则停止长寿命进程。

    这是一种有效的方法(因为 Redis 在这种情况下非常快)来检测代码是否被更改,以及是否应该为这种代码更改更新作业。

    将值保存到 Redis 的原因,“很可能”您的缓存驱动程序是 Redis。如果您将其更改为file,那么它将改为保存在文件中并向该文件发出获取请求。

    这里是related methods;

    protected function stopIfNecessary(WorkerOptions $options, $lastRestart, $job = null)
    {
        if ($this->shouldQuit) {
            $this->stop();
        } elseif ($this->memoryExceeded($options->memory)) {
            $this->stop(12);
        } elseif ($this->queueShouldRestart($lastRestart)) {
            $this->stop();
        } elseif ($options->stopWhenEmpty && is_null($job)) {
            $this->stop();
        }
    }
    
    protected function queueShouldRestart($lastRestart)
    {
        return $this->getTimestampOfLastQueueRestart() != $lastRestart;
    }
    
    protected function getTimestampOfLastQueueRestart()
    {
        if ($this->cache) {
            return $this->cache->get('illuminate:queue:restart');
        }
    }
    

    【讨论】:

    • 所以即使没有工作要执行,它也会在 Redis 中每秒检查一次illuminate:queue:restart 键值?
    • 另外,yu 说It is an efficient way to detect whether the code is changed and should the jobs should be updated for this code change,但是queue:work 不应该检测到任何代码更改。这不是队列的重点:作为守护进程工作吗?
    • 它可能在一秒钟内执行超过 1 次并乘以进程数。如果您有 1000 个并且在 queue:work 中没有设置 sleep 选项 - 那么您可能在一秒钟内看到 1000+ 个。(即使是小型实例 redis 也可以在一秒钟内处理 100K 个命令,这个是无害的)因为它们是长时间运行的进程,框架(可能是 php)可能正在缓存类的相同部分以提高性能。他们在“处理”工作时试图检测代码更改 - 我认为这是一个好方法。无需手动发出信号来警告框架“我更改了代码”。 @RaheelHasan
    • @RaheelHasan 1000+ 可能取决于进程数量、连接的实例数量以及睡眠情况等,但不会更少。正如您所说,如果它适合您的业务规则,那么完全可以。很高兴它有帮助。
    • @RaheelHasan 我从未使用过/不需要block_for,但它只是“redis-available”选项,因为它使用了BLPOP 命令。 redis.io/commands/blpop
    猜你喜欢
    • 2021-10-26
    • 1970-01-01
    • 2017-01-03
    • 2019-01-23
    • 2017-08-11
    • 2018-06-20
    • 2015-08-14
    • 2019-02-10
    • 2018-04-07
    相关资源
    最近更新 更多