Laravel队列使用中踩的坑,不报错但是队列一直再重试

/ 3评 / 2 / 11,441 次 /

使用方案

使用的Laravel框架提供的队列服务,使用artisan命令来监听队列

php artisan queue:work

使用的是事件队列,定义的Event和Listener如下:
TestEvent为触发的事件类,

TestListener为事件的监听类:

并且定义事件与监听之间的关联关系:

在我触发事件的时候使用\Event::fire(new TestEvent($product_info));

发现问题

在本地测试的时候没有发现任何异常队列,但是在线上环境却出现了很多奇怪的队列,队列一直在重试而且laravel.log日志文件中却没有看到记录有任何的异常日志。

既然没办法直观看到错误消息,只有老老实实跟一下源码了,首先从队列的监听进程开始找。

解决过程

首先找到queue:work命令的源头,这个文件就是
Illuminate\Queue\Console\WorkCommand

这里的fire函数就是队列监听的开始执行者。
紧跟下去你就会发现fire() -> runNextJob() -> \Illuminate\Queue\Work::runNextJob()。
在process函数中你会发现这里竟然使用了tryCatch来捕捉异常,



然后这里的异常处理是使用一个Event事件来处理的,
意思就是说,当Job队列发送异常时这里的异常消息必须是要你监听了两个队列错误触发的事件才行。
于是乎只能自己再去写监听类了。


在这里再去对队列的重试次数做限制,超出限制后删除队列或延迟处理。
通过对队列错误事件的监听我才知道,原来是由于在我的事件中使用了Model模型,再进入队列执行的时候,
会使用Model的主键再去反查一次模型数据,而且使用的是firstOrFail方法,可能是由于之前的一些数据被物理删除
了导致找不到的原因,这这里就报错了,而且没有删除的机制,所以队列一直在重试!
好了,终于修复了这个坑了!

总结

最后,还是以文字简单描述下这个监听工作,方便SEO啊!
使用Laravel队列时一定要记得监听
Illuminate\Queue\Events\JobExceptionOccurred;
Illuminate\Queue\Events\JobFailed;
两个事件不然发生错误队列就删除不了了,如果是在执行队列中handle函数中
一定要记得及时删除队列,使用delete()方法即可!
更多关于Laravel队列的问题可以给我留言或评论!

3条回应:“Laravel队列使用中踩的坑,不报错但是队列一直再重试”

  1. jerry cage说道:

    不是有throw $e ?

    • jiangxianli说道:

      @jerry cage 在外部函数proccess虽然有try …. catch .但是在异常捕捉后使用$this->hanleXXX函数去处理异常,然后再hanleXXX也有使用throw $e,但是外层的proccess函数 最终没有抛出这个异常。

  2. chi chi说道:

    监听事件是放在handle() 里面吗?我尝试了这种方法,卡死的报错没有获取到,只能获取到任务请求超时或请求过多次的报错

发表评论

邮箱地址不会被公开。 必填项已用*标注

5 + 1 =