美文网首页
Laravel队列执行使用频率限制

Laravel队列执行使用频率限制

作者: 众神开挂 | 来源:发表于2020-08-22 11:05 被阅读0次

    框架从5.8升级到6.0,结果好多队列执行失败了,原因很简单

    App\Jobs\XXXXX has been attempted too many times or run too long. The job may have previously timed out.
    

    先贴出原来的代码

    //设置任务执行的最大时间
    public $timeout = 120;
    
    /**
     * 通过Redis限制队列任务
     *
     * @return void
     */
    public function handle()
    {
        Redis::throttle('key')->block(0)->allow(1)->every(5)->then(function () {
            info('Lock obtained...');
    
            // 处理队列...
        }, function () {
            // 无法获取锁…
    
            return $this->release(5);
        });
    }
    

    使用了频率限制,队列会反复重新尝试执行,而且

    注意:将受限制的作业释放回队列,仍然会增加工作的总数 attempts

    这就导致重试次数过多导致任务失败,你需要放开次数限制,5.8是默认没有次数上限的,但在6.0的文档中多了这样的一段:

    基于时间的尝试

    作为另外一个选择来定义任务在失败前会尝试多少次,你可以定义一个任务超时时间。这样的话,在给定的时间范围内,任务可以无限次尝试。要定义一个任务的超时时间,在你的任务类中新增一个 retryUntil 方法:

    /**
    * 定义任务超时时间
    *
    * @return \DateTime
    */
    public function retryUntil()
    {
       return now()->addSeconds(5);
    }
    

    这样的话就可以按照实际的需求设定任务的有效的执行时间,我把时间设置为:一天+

     return now()->addSeconds(87000);
    

    队列可以正常执行了,很好!

    20200831补充,队列报错 ,RedisException(code: 0) 错误解决,异常提示如下:

    [2020-08-28 15:26:10] test.ERROR: read error on connection to 127.0.0.1:6379 {"exception":"[object] (RedisException(code: 0): read error on connection to 127.0.0.1:6379 at H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Redis\\Connections\\Connection.php:111)
    [stacktrace]
    #0 H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Redis\\Connections\\Connection.php(111): Redis->blPop(Array, 90)
    #1 H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Redis\\Connections\\PhpRedisConnection.php(168): Illuminate\\Redis\\Connections\\Connection->command('blpop', Array)
    #2 H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Queue\\RedisQueue.php(233): Illuminate\\Redis\\Connections\\PhpRedisConnection->blpop(Array, 90)
    #3 H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Queue\\RedisQueue.php(169): Illuminate\\Queue\\RedisQueue->retrieveNextJob('queues:send_mai...')
    #4 H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Queue\\Worker.php(264): Illuminate\\Queue\\RedisQueue->pop('XXX')
    #5 H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Queue\\Worker.php(118): Illuminate\\Queue\\Worker->getNextJob(Object(Illuminate\\Queue\\RedisQueue), 'XXX')
    #6 H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Queue\\Console\\WorkCommand.php(112): Illuminate\\Queue\\Worker->daemon('redis', 'XXX', Object(Illuminate\\Queue\\WorkerOptions))
    #7 H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Queue\\Console\\WorkCommand.php(96): Illuminate\\Queue\\Console\\WorkCommand->runWorker('redis', 'XXXX')
    #8 [internal function]: Illuminate\\Queue\\Console\\WorkCommand->handle()
    #9 H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Container\\BoundMethod.php(32): call_user_func_array(Array, Array)
    #10 H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Container\\BoundMethod.php(90): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
    #11 H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Container\\BoundMethod.php(34): Illuminate\\Container\\BoundMethod::callBoundMethod(Object(Illuminate\\Foundation\\Application), Array, Object(Closure))
    #12 H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Container\\Container.php(591): Illuminate\\Container\\BoundMethod::call(Object(Illuminate\\Foundation\\Application), Array, Array, NULL)
    #13 H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Console\\Command.php(192): Illuminate\\Container\\Container->call(Array)
    #14 H:\\Code\\kol\\vendor\\symfony\\console\\Command\\Command.php(255): Illuminate\\Console\\Command->execute(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Illuminate\\Console\\OutputStyle))
    #15 H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Console\\Command.php(179): Symfony\\Component\\Console\\Command\\Command->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Illuminate\\Console\\OutputStyle))
    #16 H:\\Code\\kol\\vendor\\symfony\\console\\Application.php(1000): Illuminate\\Console\\Command->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
    #17 H:\\Code\\kol\\vendor\\symfony\\console\\Application.php(271): Symfony\\Component\\Console\\Application->doRunCommand(Object(Illuminate\\Queue\\Console\\WorkCommand), Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
    #18 H:\\Code\\kol\\vendor\\symfony\\console\\Application.php(147): Symfony\\Component\\Console\\Application->doRun(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
    #19 H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Console\\Application.php(90): Symfony\\Component\\Console\\Application->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
    #20 H:\\Code\\kol\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Console\\Kernel.php(131): Illuminate\\Console\\Application->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
    #21 H:\\Code\\kol\\artisan(37): Illuminate\\Foundation\\Console\\Kernel->handle(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
    #22 {main}
    "} 
    

    解决方法:

    1. 查看config->redis中的配置文件,设置read_time_out=0,或者不做设置
     // 发送邮件队列
            'queue' => [
                'url' => env('REDIS_URL'),
                'host' => env('REDIS_HOST', '127.0.0.1'),
                'password' => env('REDIS_PASSWORD', null),
                'port' => env('REDIS_PORT', 6379),
                'database' =>env('REDIS_QUEUE_DB', 3),
            ]
    
    1. 修改redis配置中的过期时间 timeout 是否是0,0为永不过期
    2. 修改php配置文件 ,延长 default_socket_timeout 时间 ,这里我设置为60000

    相关文章

      网友评论

          本文标题:Laravel队列执行使用频率限制

          本文链接:https://www.haomeiwen.com/subject/netvjktx.html