使用场景
- 异步 - 耗时任务延迟处理,缩短请求响应时间,提高反馈效率,避免程序超时
- 重试 - 确保任务的可靠执行
配置
队列驱动支持
config/queue.php
每个队列驱动都基于底层连接,且通过属性queue
指定默认队 - 原生支持
Redis、Beanstalkd、Database(需:php artisan queue:table && php artisan migrate)、Sqs、IronMQ
等 - 原生测试支持
sysnc同步驱动(立即执行Job)
、null驱动(简单丢弃Job)
- 开源第三方驱动支持
RabbitMQ、Kafka
等
Fail表准备
php artisan queue:failed-tablephp artisan migrate
Job创建
php artisan make:job MyJob
(默认实现接口ShouldQueue
以队列化的异步执行)- 构造函数传参
model实例
,则仅有ID
会被序列化并存入队列,消费时通过ID
于数据库重新取回 $myJob = new MyJob(); dispatch($myJob);
handle
方法:Job
消费逻辑failed(Exception $exception)
方法:Job
失败后的收尾逻辑
- 同类型
Job
建议投递到同一队列上(比如短信Job
和邮件Job
都投递到notification
队列上)
Job定制
- 指定延迟:
$myJob->delay(Carbon::now()->addMinutes(10))
- 指定队列:
$myJob->onQueue(指定队)
- 指定连接:
$myJob->onConnection(指定连接)
- 指定Job重试次数:
public $tries = 3;
(Job执行中发生Excepion则被退回队列并重试) - 指定Job运行超时:
public $timeout = 60;
(秒)
##Queue执行
- 保持运行直至手动停止
- 长时间运行进程,并使用启动时的代码上下文
--queue
参数先后顺序可指定优先级- 留意在完成Job后释放相关资源
# 启动队列执行器* 生产环境(高效模式):php artisan queue:work --daemon [--quiet ] [--delay=3] [--sleep=队列空后的休眠时间] [--tries=3] [--timeout=30] [--memory=默认128M] [--queue=队列1,队列2] [指定连接]* 测试环境(每次重载上下文):php artisan queue:listen [--tries=3] [--timeout=30] [--sleep=队列空后的休眠时间] [--queue=队列1,队列2] [指定连接]# 重启队列执行器(以便在项目部署时重载代码上下文)php artisan queue:restart
Queue 超时&过期
- 过期(队列连接的
retry_after
属性)指定了Job
重试的等待时间 - 超时(
--timeout
)指定了处理Job
的子队列执行器被kill
前的超时时间 - 超时应该确保比过期时间短几秒,这样
Job
会先超时被kill
,然后在到达过期时间后被重试
Job失败
失败流程
- 每当
Job
失败,执行failed(Exception $exception)
方法中失败后的收尾逻辑 - 如果
Job
在最终尝试后还失败,则入表failed_jobs
FailedJob处理
- 罗列
php artisan queue:failed
- 重试
php artisan queue:retry all|jobID
- 删除
php artisan queue:forget all|jobID
- 清空
php artisan queue:flush
Job监听
# AppServiceProvider::boot 中注册Job事件的监听//$event->connectionName//$event->job->payload()//$event->exceptionQueue::before(function(JobProcessing $event){});Queue::after(function(JobProcessed $event){});Queue::failing(function(JobFailed $event){});# queue worker请求Job前Queue::looping(function(){ # 可处理一些回滚 while (DB::transactionLevel() > 0) { DB::rollBack(); }});
队列消费服务
通过supervisor
启动队列消费服务
进程守护
队列消费服务多进程
方式消费队列中的Job
配置
# /etc/supervisor/conf.d/queue-worker-test.conf [program:queue-worker-test] process_name=%(program_name)s_%(process_num)02d directory=/var/www/html command=php artisan queue:work --daemon --quiet --delay=3 --sleep=3 --tries=3 --memory=1024 --queue=test autostart=true autorestart=true user=www numprocs=5 #当>1时, process_name必须有%(process_num) priority=997 stopsignal=QUIT redirect_stderr=true stdout_logfile=/dev/null stdout_logfile_maxbytes=0 stdout_logfile_backups=0 stderr_logfile=/dev/null stderr_logfile_maxbytes=0 stderr_logfile_backups=0
启动
sudo supervisorctl reread sudo supervisorctl update sudo supervisorctl start queue-worker-test:*