在生产环境管理队列任务的重试


通过重试避免任务标记失败

每当处理器进程从队列系统获取一个任务,就被认为是尝试一次,即便是这个任务压根没有运行。我们可以通过设置尝试次数多次重试某个任务,避免其被标记为执行失败。

如下几种情况都会导致队列任务被标记为执行失败:

  • 由于网络原因导致下载任务载荷数据失败;
  • 反序列化任务载荷数据失败;
  • 任务执行超时;
  • 执行任务时抛出未处理异常;
  • 由于网络问题导致标记任务已处理失败。

可以看到,即便任务没有开始运行,也有可能失败,并且即便任务已经执行成功,仍然可能被标记失败。

默认情况下,Laravel 只允许每个队列任务执行一次,在本地开发环境,这种配置可以让你快速定位问题,但是如果在生产环境,可以执行多次提高任务处理成功的概率:

-w634

或者直接在任务类中定义 tries 属性:

-w618

基于任务处理失败的重试

如果是 handle 方法抛出异常或者超时导致任务处理失败,处理器进程会立即将任务推送回队列进行重试。

不过,有时候你可能想要延迟一会儿,这可以通过 --backoff 选项或者在任务类中定义 backoff 属性或者 backoff 方法来实现:

-w685

还可以定义延迟跃迁:

-w702

基于处理器失败的重试

队列任务执行失败后,如果处理器进程和队列存储驱动之间的通信失败,尝试次数已经被计算,但是处理器进程无法配置延迟。

这种情况下,队列管理器会基于连接实例上的 retry_after 配置将任务推送回队列然后重试:计时器从处理器从队列获取任务开始计时,经过配置的 retry_after 时间后,该任务可以再度被处理器进程获取进行处理。

需要确保 retry_after 比任何任务执行耗时都长。

基于时间段的重试

有时候你可能想要在指定时间后重试,这可以通过 retryUtil 属性和方法来实现:

-w656

该任务会重试 10 次或者直到指定的时间戳再重试(2020-07-30),如果你想要无限重试,可以将 tries 设置为 0。

定义时间时还可以通过日期函数:

-w623

对于无限重试任务,最好通过 backoff 定义延时跃迁,避免队列一直处于繁忙状态。

队列任务处理异常和超时

将任务推送回队列也算作一次尝试:

-w626

如果是频率限制导致的回推,十次回推也会被标记为失败。

当然,如果任务运行过程中出现异常或超时,你肯定不想反复重试,可以定义 $maxExceptions 属性限制异常上限:

-w671

$maxExceptions 必须小于 tries,除非 tries 等于 0。


点赞 取消点赞 收藏 取消收藏

<< 上一篇: 如何确保 Redis 驱动消息队列的高可用

>> 下一篇: 在应用部署时重启队列任务处理进程