Laravel队列执行使用频率限制

2020-08-22  本文已影响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
上一篇 下一篇

猜你喜欢

热点阅读