当创建队列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格式的任务。因为这是在自由转码队列中设置的,所以它的作用有限。大型项目实战直播加入(点击→)我的直播群677079770


检查尝试次数

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){// 如果发布服务器已被停用,请删除此队列jobif ($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){// 如果发布服务器已被停用,请删除此队列jobif ($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){// 如果发布服务器已被停用,请删除此队列jobif ($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));}
}

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

phper在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家需要的(点击→)我的官方群677079770

PHP Laravel 队列技巧:Fail、Retry 或者 Delay相关推荐

  1. Php laravel 队列,Laravel 的队列系统介绍

    这篇文章主要介绍的内容是关于Laravel 的队列系统介绍,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 Laravel 队列为不同的后台队列服务提供统一的 API , 例如 Bean ...

  2. laravel 队列queue

    队列 Laravel队列服务为各种不同的后台队列提供统一的API 允许推迟耗时任务(例如发送邮件)的执行,从而大幅提高web请求速度 配置文件 Config/queue.php 支持模式 Suppor ...

  3. supervisor 守护php,laravel队列之Supervisor守护进程(centos篇)

    前言 unbutun和centos均为linux系统,官方为我们提供了Homestead可以很好的模拟在服务器中的开发和运行.之前写了一篇基于Homestead(unbutun)关于Superviso ...

  4. Laravel 队列:如何查看队列报错信息

    Laravel 队列在执行时,如黑盒一样,出错时我们该如何调试呢? 方法一.sync 驱动 如果你在开发环境,修改 .env: QUEUE_DRIVER=sync 这样就可以直接通过 Web 请求触发 ...

  5. php加入队列失败,Laravel队列使用中踩的坑,不报错但是队列一直再重试

    使用方案 使用的Laravel框架提供的队列服务,使用artisan命令来监听队列 使用的是事件队列,定义的Event和Listener如下: TestEvent为触发的事件类, TestListen ...

  6. 使用supervisor管理laravel队列 - 配置文件supervisord.conf

    相关文章 上一篇:使用supervisor管理laravel队列 ,此篇重点性描述了我本地配置supervisor的全部过程:但是并未介绍为啥这么配置,这里,我就来记录一下配置supervisor的各 ...

  7. 使用Supervisor来管理你的Laravel队列

    使用Supervisor来管理你的Laravel队列 Laravel官网教程中,并没有提到用它来写CLI应用,即守护进程或者可执行脚本.但是它却提供了更加便捷的队列(Queue)功能. 简明思路:其实 ...

  8. Laravel 队列发送邮件

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

  9. laravel 队列学习

    s d f大撒发 转载于:https://www.cnblogs.com/toyanglei/p/5911707.html

最新文章

  1. Machine Learning week 9 quiz: programming assignment-Anomaly Detection and Recommender Systems
  2. Lighttpd源码分析之状态机与插件
  3. Boost:基于Boost的管道pipeline通信
  4. 20135219洪韶武——信息安全系统设计基础第五周学习总结
  5. iNeuLink硬件网关与iNeuOS工业互联网操作系统互联互通应用案例
  6. JUnit和Hamcrest:在assertEquals上进行改进
  7. 风控模型师面试准备--技术篇(逻辑回归、决策树、集成学习)
  8. h标签对html网页的作用,网页H标签SEO价值的说明与举例
  9. _bzoj1007 [HNOI2008]水平可见直线【单调栈】
  10. 修改网页代码_网站建设中使用简洁规范代码的重要性
  11. 数字藏品APP源码,无加密
  12. 使用vue创建项目的详细步骤
  13. 电信光猫 友华PT921G 研究
  14. 超级会员创作者收益说明
  15. ryuyan 方差分析_如何使用R语言做不同设计的方差分析(ANOVA)、简单效应检验、事后多重比较?...
  16. 2017,我的面试复盘
  17. python调用多级目录中的文件_python复制多层目录下的文件至其他盘符对应的目录中...
  18. WLAN AP安全策略中WPA认证与WPA2认证的差异
  19. mysql 转义字符 escape_mysql 的Escape转义字符串
  20. 分享idea中一些好用的插件

热门文章

  1. 【机房收费系统个人版】三层登陆
  2. 使用VB.Net操作Excel输出重复内容的表格
  3. 正交设计 python算法_Python实现正交实验法-高级篇
  4. [MATLAB] 读取ASII文件中的复数数据
  5. Android App的国际化-各国语言缩写
  6. gitlab运行后修改存储位置
  7. html中打印部分内容,设置网页打印区域
  8. WHQL认证产品可以 现在又可以查询了
  9. 压缩视频文件怎么压缩最小?
  10. C# Microsoft.Office.Interop.Word设置Word页脚之添加当前页数