当创建队列jobs、监听器或订阅服务器以推送到队列中时,您可能会开始认为,一旦分派,队列工作器决定如何处理您的逻辑就完全由您自己决定了。

嗯……并不是说你不能从作业内部与队列工作器交互,但是通常情况下,哪怕你做了,也是没必要的。

这个神奇的骚操作的出现是因为“InteractsWithQueue”这个trait。.当排队作业正在从队列中拉出, 这个 [CallQueuedListener](https://github.com/laravel/framework/blob/5.8/src/Illuminate/Events/CallQueuedListener.php#L90-L104) 会检查它是否在使用 InteractsWithQueue trait, 如果是的话,框架会将底层的“队列jobs”实例注入到内部。

这个 “任务” 实例类似于一个包装了真正的 Job 类的驱动,其中包含队列连接和尝试等信息。

背景
我将以一个转码 Job 为例。 这是一个将广播音频文件转换成192kbps MP3格式的任务。因为这是在自由转码队列中设置的,所以它的作用有限。

检查尝试次数
attempts()是被调用的第一个方法, 顾名思义,它返回尝试次数,一个队列 job总是伴随着一个attempt启动。

此方法旨在与其他方法一起使用 ..., 类似 fail() 或者 release() (delay). 为了便于说明,我们将通知用户第几次重试: 每次我们尝试在空闲队列中转换(转换代码)时,我们都会通知用户我们正在第几次重试,让他可以选择取消将来的转换(转换代码)。

 <?php
namespace App\Jobs;
use App\Podcast;
use Transcoder\Transcoder;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use App\Notifications\PodcastTranscoded;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use App\Notifications\RetyingPodcastTranscode;
class TranscodePodcast
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Transcoder Instance
*
* @var \App\Podcast
*/
protected $podcast;
/**
* 创建一个新的转码podcast实例。
*
* @param \App\Podcast $podcast
* @return void
*/
public function __construct(Podcast $podcast)
{
$this->podcast = $podcast;
}
/**
* 执行队列job.
*
* @param \Transcoder\Transcoder $podcast
* @return void
*/
public function handle(Transcoder $transcoder)
{
// 告诉用户我们第几次重试
if ($this->attempts() > 1) {
$this->podcast->publisher->notify(new RetryingPodcastTranscode($this->podcast, $this->attempts());
}
$transcoded = $this->transcoder->setFile($event->podcast)
->format('mp3')
->bitrate(192)
->start(); // 将转码podcast与原始podcast关联
$this->podcast->transcode()->associate($transcoded); // 通知podcast的发布者他的podcast已经准备好了 $this->publisher->notify(new PodcastTranscoded($this->podcast));
}
}

告诉用户我们将在第几次时重试某些内容,这在逻辑预先失败时很有用,让用户(或开发人员)检查出了什么问题,但当然您可以做更多的事情。

就我个人而言,我喜欢在“Job作业”失败后再这样做,如果还有重试时间,告诉他我们稍后会重试当然,这个例子只是为了举例说明。

删除作业队列 Job
第二个方法就是 delete(). 跟你猜想的一样,您可以从队列中删除当前的“队列 Job”。 当队列 Job或侦听器由于多种原因排队后不应处理时,这将会很方便,例如,考虑一下这个场景:在转码发生之前,上传podcast的发布者由于任何原因(比如TOS冲突)被停用,我们应该不处理podcast。

我们将在前面的示例中添加该代码:

 <?php
namespace App\Jobs;
use App\Podcast;
use Transcoder\Transcoder;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use App\Notifications\PodcastTranscoded;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use App\Notifications\RetyingPodcastTranscode;
class TranscodePodcast
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Transcoder Instance
*
* @var \App\Podcast
*/
protected $podcast;
/**
* 创建一个新的转码podcast实例。
*
* @param \App\Podcast $podcast
* @return void
*/
public function __construct(Podcast $podcast)
{
$this->podcast = $podcast;
}
/**
* 执行队列 job.
*
* @param \Transcoder\Transcoder $podcast
* @return void
*/
public function handle(Transcoder $transcoder)
{
// 如果发布服务器已被停用,请删除此队列job
if ($this->podcast->publisher->isDeactivated()) {
$this->delete();
}
// 告诉用户我们第几次重试
if ($this->attempts() > 1) {
$this->podcast->publisher->notify(new RetryingPodcastTranscode($this->podcast, $this->attempts());
}
$transcoded = $this->transcoder->setFile($event->podcast)
->format('mp3')
->bitrate(192)
->start(); // 将转码podcast与原始podcast关联
$this->podcast->transcode()->associate($transcoded); // 通知podcast的发布者他的podcast已经准备好了
$this->publisher->notify(new PodcastTranscoded($this->podcast));
}
}

如果需要删除可能已删除的模型上的作业,则可能需要 设置 [$deleteWhenMissingModels](https://laravel.com/docs/5.8/queues#ignoring-missing-models) 为真 t避免处理不存在的东西。

失败的队列job
当您需要控制人为破坏逻辑时,这非常非常方便, 因为使用空的“return”语句会将“Job”标记为已成功完成。您可以强制使排队的作业失败,希望出现异常,允许处理程序在可能的情况下稍后重试。

这使您在作业失败时可以更好地控制在任何情况下,也可以使用“failed()”方法, 它允许你 失败后执行任何清洁操纵, 比如通知用户或者删除一些东西。

在此示例中,如果由于任何原因(如 CDN 关闭时)无法从存储中检索podcast ,则作业将失败,并引发自定义异常。

 <?php
namespace App\Jobs;
use App\Podcast;
use Transcoder\Transcoder;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use App\Exceptions\PodcastUnretrievable;
use App\Notifications\PodcastTranscoded;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use App\Notifications\RetyingPodcastTranscode;
class TranscodePodcast
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* 转码器实例
*
* @var \App\Podcast
*/
protected $podcast;
/**
* 创建一个新的转码Podcast实例。
*
* @param \App\Podcast $podcast
* @return void
*/
public function __construct(Podcast $podcast)
{
$this->podcast = $podcast;
}
/**
* 执行队列 job.
*
* @param \Transcoder\Transcoder $podcast
* @return void
*/
public function handle(Transcoder $transcoder)
{
// 如果发布服务器已被停用,请删除此队列job
if ($this->podcast->publisher->isDeactivated()) {
$this->delete();
}
//如果podcast不能从storage存储中检索,我们就会失败。
if ($this->podcast->fileDoesntExists()) {
$this->fail(new PodcastUnretrievable($this->podcast));
}
// 告诉用户我们第几次重试
if ($this->attempts() > 1) {
$this->podcast->publisher->notify(new RetryingPodcastTranscode($this->podcast, $this->attempts());
} $transcoded = $this->transcoder->setFile($event->podcast)
->format('mp3')
->bitrate(192)
->start(); // 将转码podcast与原始podcast关联
$this->podcast->transcode()->associate($transcoded); // 通知podcast的发布者他的podcast已经准备好了
$this->publisher->notify(new PodcastTranscoded($this->podcast));
}
}

现在,进入最后的方法。

释放(延迟)队列job
这可能是trait性状的最有用的方法, 因为它可以让你在未来进一步推动这项队列job. 此方法用于 队列job速率限制.

除了速率限制之外,您还可以在某些不可用但希望在不久的将来使用它的情况下使用它同时,避免先发制人地失败。

在最后一个示例中,我们将延迟转码以备稍后使用:如果转码器正在大量使用,我们将延迟转码5分钟直到负载降低。

 <?php
namespace App\Jobs;
use App\Podcast;
use Transcoder\Transcoder;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use App\Exceptions\PodcastUnretrievable;
use App\Notifications\PodcastTranscoded;
use Illuminate\Queue\InteractsWithQueue;
use App\Notifications\TranscoderHighUsage;
use Illuminate\Foundation\Bus\Dispatchable;
use App\Notifications\RetyingPodcastTranscode;
class TranscodePodcast
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Transcoder Instance
*
* @var \App\Podcast
*/
protected $podcast;
/**
* 创建一个新的转码podcast实例。
*
* @param \App\Podcast $podcast
* @return void
*/
public function __construct(Podcast $podcast)
{
$this->podcast = $podcast;
}
/**
* 执行队列job.
*
* @param \Transcoder\Transcoder $podcast
* @return void
*/
public function handle(Transcoder $transcoder)
{
// 如果发布服务器已被停用,请删除此队列job
if ($this->podcast->publisher->isDeactivated()) {
$this->delete();
}
// 如果podcast不能从storage存储中检索,我们就会失败。
if ($this->podcast->fileDoesntExists()) {
$this->fail(new PodcastUnretrievable($this->podcast));
} // 如果转码器使用率很高,我们将
// t延迟转码5分钟. 否则我们可能会有拖延转码器进程的危险
// 它会把所有的转码子进程都记录下来。
if ($transcoder->getLoad()->isHigh()) {
$delay = 60 * 5;
$this->podcast->publisher->notify(new TranscoderHighUsage($this->podcast, $delay));
$this->release($delay);
}
// 告诉用户我们第几次重试
if ($this->attempts() > 1) {
$this->podcast->publisher->notify(new RetryingPodcastTranscode($this->podcast, $this->attempts());
} $transcoded = $this->transcoder->setFile($event->podcast)
->format('mp3')
->bitrate(192)
->start(); // 将转码podcast与原始podcast关联
$this->podcast->transcode()->associate($transcoded); // 通知podcast的发布者他的podcast已经准备好了
$this->publisher->notify(new PodcastTranscoded($this->podcast));
}
}

我们可以使用一些特殊方法,例如,获得分配给转码器的一些时隙,如果转码器时隙已满,则延迟作业。 在排队的工作中,你能做的就只有这些了。排队愉快。

PHP Laravel 队列技巧:Fail、Retry 或者 Delay的更多相关文章

  1. Laravel 队列使用

    触发 任务的触发,主要的实现是在IlluminateFoundationBusDispatchesJobs这个trait中实现的,其只包含两个方法 protected function dispatc ...

  2. laravel 队列服务使用总结

    laravel 队列服务使用总结 使用步骤 配置队列驱动 //env文件,有的版本是QUEUE_DRIVER QUEUE_CONNECTION=database 迁移队列需要的数据表,在数据库中生成j ...

  3. Laravel 队列不执行的原因,job缓存

    laravel关于异步消息队列queue不生效(job缓存)解决办法 php artisan queue:restart 每次修改代码都需要执行上面的命令,执行后成功解决! 然后再次执行 php ar ...

  4. laravel队列使用

    1.修改.env中queue_driver = databases 2.php artisan queue:table 在database 目录下migrations里面有对应的表 3.执行迁移文件 ...

  5. 一些实用的 Laravel 小技巧

    Laravel 中一些常用的小技巧,说不定你就用上了. 1.侧栏 网站一般都有侧栏,用来显示分类,标签,热门文章,热门评论啥的,但是这些侧栏都是相对独立的模块,如果在每一个引入侧栏的视图中都单独导入与 ...

  6. laravel队列

    三种情况: queue:work 默认只执行一次队列请求, 当请求执行完成后就终止; queue:listen 监听队列请求, 只要运行着, 就能一直接受请求, 除非手动终止; queue:work ...

  7. laravel队列-让守护进程处理耗时任务

    待解决的问题 最近在做一个服务器集群管理的web项目,需要处理一些极其耗时的操作,比如磁盘格式化分区.对于这个需求,最开始的想法是,为了让节点上的rpc(远程过程调用) service端尽可能简单(简 ...

  8. laravel 队列发送邮件

    批量处理任务的场景在我们开发中是经常使用的,比如邮件群发,消息通知,短信,秒杀等等,我们需要将这个耗时的操作放在队列中来处理,从而大幅度缩短Web请求和相应的时间.下面讲解下Laravel中队列的使用 ...

  9. laravel队列,事件简单使用方法

    A.队列的使用 1.队列配置文件存储在 config/queue.php 根据自己的情况进行配置 2..env文件 QUEUE_DRIVER=database(根据个人情况配置,redis等) 3.创 ...

随机推荐

  1. oracle 分区表(子分区)收缩笔记

    思路1.首先移动子分区到别的表空间.2.收缩数据文件.3.再把子分区移回原表空间. ---------------------------------------------生成发送报告移动子分区语句 ...

  2. iguana::json/xml 序列化框架

    环境:win10  vs2017  c++17  boost 1.下载源码:https://github.com/qicosmos/iguana 2.创建工程,包含源码目录.boost库目录:boos ...

  3. halcon小结

    持更 应用范围 (罗列自官方帮助文档,以后有空了按照需求展开叙述) 1. 安全系统 2. 表面检测 3. 定位 4. 二维测量比较 5. 二维码识别 6. 二维位置定位 7. 二维物体识别 8. 光学 ...

  4. Springboot项目的jar包目录结构

    上图为一个由Luyten工具反编译后的一个jar包 说明: SpringBoot提供的bootstrap的类是放到包的最外面,比如上面的org.springframework.boot.loader. ...

  5. SpringBoot-Mysql模板多数据源加载

    SpringBoot-Mysql模板多数据源加载 qq交流群: 812321371 微信交流群: MercyYao 简介 在 java 项目里常用到 mysql 多数据源操作.结合 springboo ...

  6. javascript学习总结之对象的深拷贝和浅拷贝

    前言 最近在写ES6的文章的时候发现重复遇到关于javascript深拷贝和浅拷贝的问题,然后查找了一些资料,根据资料和自己的理解做了以下笔记,毕竟javascript关于深拷贝和浅拷贝的问题在一些面 ...

  7. Mongoose-modified-at 时间自动记录插件介绍

    Mongoose-modified-at 是一款自动更新字段变化时间并记录到数据库中的 Mongoose 插件,类似 Mongoose 自带的 timestamps 功能. 使用场景 让我们考虑一个场 ...

  8. 深度讲解Linux内存管理和Linux进程调度-打通任督二脉

    我在多年的工程生涯中发现很多工程师碰到一个共性的问题:Linux工程师很多,甚至有很多有多年工作经验,但是对一些关键概念的理解非常模糊,比如不理解CPU.内存资源等的真正分布,具体的工作机制,这使得他 ...

  9. C# 表达式树 Expression

    表达式树是定义代码的数据结构. 它们基于编译器用于分析代码和生成已编译输出的相同结构. 几种常见的表达式 BinaryExpression 包含二元运算符的表达式 BinaryExpression b ...

  10. 小白学 Python(11):基础数据结构(元组)

    人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...