重试执行失败的队列任务
失败队列任务重试
Laravel 消息队列支持对执行失败的任务进行重试(详见 Laravel 队列文档处理失败的任务部分),执行失败的任务会被存储在 failed_jobs
数据表中,你需要运行如下 Artisan 命令创建这张数据表:
php artisan queue:failed-table
php artisan migrate
其表结构如下所示:
其中包含了队列驱动、队列名称、以及序列化的任务类实例,通过这些信息可以反序列化出队列任务进行重试。
你可以运行 queue:retry
命令通过指定任务 ID 来重试对应的队列任务(ID 放置在命令最后,ID 值就是 failed_jobs
数据表对应记录的 id
字段值):
php artisan queue:retry 300
指定最大尝试次数
但是这样太被动了,也不方便运维,取而代之的,你可以在启动队列处理器进程时通过 --tries
参数指定是否对失败任务进行重试,以及最大尝试次数(含第一次运行,所以真正的重试次数等于该参数值减一):
php artisan queue:work --tries=3
失败重试的底层原理也很简单,就是将失败任务重新推送到队列,在下次被轮询到时再执行一次,不过每执行一次会更新任务实例的 attempts
字段值,如果已经超过 --tries
指定的次数,则将其丢弃,不再重试。
此外,还可以在任务类中通过设置 tries
属性值来指定最大尝试次数:
这样一来,就不用在队列处理器启动命令中手动设置 tries
参数了,Laravel 会自动基于这个配置对失败任务进行重试:
php artisan queue:work
这样做的另一个好处是可以为不同的队列任务设置不同的尝试次数,更加灵活:
需要注意的是,如果在任务类和 Artisan 命令中都设置了最大尝试次数,那么任务类中的 tries
属性值会覆盖命令行中的 tries
参数值。
延迟重试
如果消息队列负载很高,可以延迟失败任务的重试,避免某个反复失败的任务占用过多的系统资源,阻塞后续其他正常队列任务推送到消息队列执行。这可以通过在任务类设置 backoff
属性来实现:
或者在 Artisan 命令中设置 --backoff
参数:
php artisan queue:work redis --tries=3 --backoff=60
以上两种实现功效一样,都是表示队列任务执行失败后,延迟 60 秒推送到消息队列重试,基本用法和优先级和最大尝试次数一样,不再赘述。
Laravel 8.0 之前对应的属性值是
retryAfter
,命令行参数也不是--backoff
,而是--delay
,这一点在使用更早版本的 Laravel 时需要注意下。
跳跃式延迟
不过某些耗时任务 60 秒可能还没有执行完成,可以每次重试后在上一次基础上延长延迟时间实现「跳跃式」延迟:
以上配置的含义是第一次重试延迟 60 秒,第二次重试延迟 120 秒:
同理,你也可以通过在 Artisan 命令中通过 backoff
参数设置「跳跃式延迟」:
php artisan queue:work --backoff=60,120
如果最大尝试次数超过 backoff
配置的数量,则后续重试以最后一个延迟时间值为准,所以,如果这里的最大尝试次数配置为 5,则后面的重试延迟时间都是 120 秒。当然,你也可以为 backoff
配置更多的延迟时间跳跃值。
5 Comments
如果不进行失败重试,则需要怎么配置
tries = 1 就好了呀
tries =1 表示不重试,tries=0 表示啥
应该是一样的 你试下
好的