PHP Laravel 队列技巧:Fail、Retry 或者 Delay
当创建队列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的更多相关文章
- Laravel 队列使用
触发 任务的触发,主要的实现是在IlluminateFoundationBusDispatchesJobs这个trait中实现的,其只包含两个方法 protected function dispatc ...
- laravel 队列服务使用总结
laravel 队列服务使用总结 使用步骤 配置队列驱动 //env文件,有的版本是QUEUE_DRIVER QUEUE_CONNECTION=database 迁移队列需要的数据表,在数据库中生成j ...
- Laravel 队列不执行的原因,job缓存
laravel关于异步消息队列queue不生效(job缓存)解决办法 php artisan queue:restart 每次修改代码都需要执行上面的命令,执行后成功解决! 然后再次执行 php ar ...
- laravel队列使用
1.修改.env中queue_driver = databases 2.php artisan queue:table 在database 目录下migrations里面有对应的表 3.执行迁移文件 ...
- 一些实用的 Laravel 小技巧
Laravel 中一些常用的小技巧,说不定你就用上了. 1.侧栏 网站一般都有侧栏,用来显示分类,标签,热门文章,热门评论啥的,但是这些侧栏都是相对独立的模块,如果在每一个引入侧栏的视图中都单独导入与 ...
- laravel队列
三种情况: queue:work 默认只执行一次队列请求, 当请求执行完成后就终止; queue:listen 监听队列请求, 只要运行着, 就能一直接受请求, 除非手动终止; queue:work ...
- laravel队列-让守护进程处理耗时任务
待解决的问题 最近在做一个服务器集群管理的web项目,需要处理一些极其耗时的操作,比如磁盘格式化分区.对于这个需求,最开始的想法是,为了让节点上的rpc(远程过程调用) service端尽可能简单(简 ...
- laravel 队列发送邮件
批量处理任务的场景在我们开发中是经常使用的,比如邮件群发,消息通知,短信,秒杀等等,我们需要将这个耗时的操作放在队列中来处理,从而大幅度缩短Web请求和相应的时间.下面讲解下Laravel中队列的使用 ...
- laravel队列,事件简单使用方法
A.队列的使用 1.队列配置文件存储在 config/queue.php 根据自己的情况进行配置 2..env文件 QUEUE_DRIVER=database(根据个人情况配置,redis等) 3.创 ...
随机推荐
- windows系统安全日志取证工具
0x01 关于日志 Windows安全事件日志中详细记录了是谁在什么时候通过什么手段登录到系统或者注销了登录,通过分析该日志可以详细了解服务器的安全情况以及必要时的取证工作. 0x02 查看日志 传统 ...
- Android Studio 模拟器Intel 加速
Starting emulator for AVD 'Phone1'emulator: ERROR: x86 emulation currently requires hardware acceler ...
- [七年技术总结系列][理论篇]-RBAC权限模型由浅入深
权限部分将分两章介绍,第一章由浅入深介绍权限理论知识及应用,第二章介绍具体实现.后期再讲述中间件的使用时,还会插入一些权限内容,本质上属于中间件的应用. 权限模块是业务系统最常见.最基本的子集.本章假 ...
- shell传递参数(三)
$n:n代表一个数字,指执行脚本的第n个参数.特别地,$0指执行的文件名 [root@ipha-dev71- exercise_shell]# cat test.sh #!/bin/bash echo ...
- linux系统状态网络、权限、用户大杂烩
来来来,我们聊一下liunx系统相关的知识!! 首先从查询网络配置开始 ifconfig 查询.设置网卡和ip等参数 ifup,ifdown 脚本命令,更简单的方式启动关闭网络 ip命令是结合了ifc ...
- 图像处理 - ImageMagick 简单介绍与案例
在客户端我们可以用 PhotoShop 等 GUI 工具处理静态图片或者动态 GIF 图片,不过在服务器端对于 WEB 应用程序要处理图片格式转换,缩放裁剪,翻转扭曲,PDF解析等操作, GUI 软件 ...
- 由浅入深:Python 中如何实现自动导入缺失的库?
在写 Python 项目的时候,我们可能经常会遇到导入模块失败的错误:ImportError: No module named 'xxx' 或者 ModuleNotFoundError: No mod ...
- 最近学到的ABTest知识
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 如果之前看过我文章的同学就知道我在工作中搞的是推送系 ...
- vue-class-component使用Mixins
vue-class-component提供了mixinshelper函数,以类样式的方式使用mixins.通过使用mixins帮助程序,TypeScript可以推断mixin类型并在组件类型上继承它们 ...
- 小白学 Python(10):基础数据结构(列表)(下)
人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...