当创建队列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. AWD攻防工具脚本汇总(二)

    情景五:批量修改ssh密码 拿到官方靶机第一件事改自己机器的ssh密码,当然也可以改别人的密码~ import paramiko import sys ssh_clients = [] timeout ...

  2. shark恒破解笔记3-EAX决定胜负

    PEID查壳 od载入 输入假的注册码 查找出错字符串 往上查找是否有关键跳转和关键call 可以看到此处有个je跳转 实现了跳转,并且跳过了我们注册成功的地址 网上查找这个跳转的关键call,这个c ...

  3. 基于canvas实现钟表

    原理说明 1.通过arc方法实现钟表外环: 2.通过line实现钟表时针,分针,秒针和刻度标志的绘制,基于save和restore方法旋转画布绘制不同角度的指针: 3.通过font方法实现在画布上绘制 ...

  4. 第三方应用 flashfxp,filezilla提权

    filezilla 提权 filezilla 开源的ftp服务器 默认监听14147端口 默认安装目录下有个敏感文件 filezillaserver.xml(包含用户信息) filezillaserv ...

  5. 2.2 C语言_实现数据容器vector(排序功能)

    上一节我们说到我们己经实现了一般Vector可以做到的自动扩充,告诉随机存取,那么现在我们需要完成vector的一个排序的功能. 排序算法我们网上一百度哇~~!很常见的就有8大排序算法: 1.选择排序 ...

  6. 玩转u8g2 OLED库,一篇就够

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  7. 图像配准SIFT

    (一)图像特征匹配--SIFT 1.1 SIFT背景简介 SIFT算法是David Lowe在1999年提出的局部特征描述子,并在2004年深入发展和完善. SIFT算法是在尺度空间进行特征检测并确定 ...

  8. 09 python学习笔记-操作excel(九)

    python操作excel使用xlrd.xlwt和xlutils模块,xlrd模块是读取excel的,xlwt模块是写excel的,xlutils是用来修改excel的.这几个模块可以使用pip安装, ...

  9. 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU硬件那些事(2.2)- 在串行NOR Flash XIP调试原理

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列EVK在串行NOR Flash调试的原理. 本文是i.MXRT硬件那些事系列第二篇的续集,在第二篇首集 ...

  10. Docker之构建上下文详解

    昨天写了使用 Dockerfile 定制镜像.其中构建上下文这一块没有写,今天把这一块单独拿出来写一下. Docker镜像构建 简单说下构建镜像步骤: cd Dockerfile 所在目录; 执行 d ...