Laravel使用Queue队列的技巧汇总


Posted in PHP onSeptember 02, 2019

前言

Laravel 队列为不同的后台队列服务提供统一的 API,例如 Beanstalk,Amazon SQS,Redis,甚至其他基于关系型数据库的队列。队列的目的是将耗时的任务延时处理,比如发送邮件,从而大幅度缩短 Web 请求和相应的时间。

队列配置文件存放在 config/queue.php 。每一种队列驱动的配置都可以在该文件中找到,包括数据库,Beanstalkd ,Amazon SQS,Redis,以及同步(本地使用)驱动。其中还包含了一个 null 队列驱动用于那些放弃队列的任务

为什么使用队列?

一般来说使用队列是为了:

异步
重试

也许你还有其他的理由使用队列,但是这应该是最基本的两个原因。

什么情况使用队列?

了解了为什么使用队列,那么一般有这么几类任务使用队列:

耗时比较久的,比如上传一个文件后进行一些格式的转化等。

需要保证送达率的,比如发送短信,因为要调用别人的 api,总会有几率失败,那么为了保证送达,重试就必不可少了。
使用队列的时候一定要想明白一个问题,这个任务到底是不是可以异步,如果因为异步会导致问题,那么就要放弃使用队列。

驱动的必要设置

database.php

在 database.php 配置文件中对 redis 数据库部分进行配置,默认有一个 default 连接,就用这个好了:)
根据这个默认连接中需要的配置项,编辑 .env 配置文件,将其中的 REDIS_HOST、REDIS_PASSWORD、REDIS_PORT 填写成自己服务器中 Redis 的相应值。

queue.php

首先需要去 .env 中配置 QUEUE_DRIVER,因为现在打算用 Redis,所以配置成 redis。

接着配置 queue.php 里 connections 部分的 redis 连接,其中 connection 对应的值就是 database.php 中 redis 的那个 default 连接。

数据库

要使用 database 这个队列驱动的话,你需要创建一个数据表来存储任务。你可以用 queue:table 这个 Artisan

php artisan queue:table

处理失败的任务

有时候你队列中的任务会失败。不要担心,本来事情就不会一帆风顺。

Laravel 内置了一个方便的方式来指定任务重试的最大次数。当任务超出这个重试次数后,它就会被插入到 failed_jobs 数据表里面。要创建 failed_jobs 表的迁移文件,你可以用 queue:failed-table 命令,接着使用 migrate Artisan 命令生成 failed_jobs 表:

php artisan queue:failed-table

命令来创建这个数据表的迁移。当迁移创建好以后,就可以用 migrate 这条命令来创建数据表:

php artisan migrate

执行命令讲解

php artisan queue:work --daemon --quiet --queue=default --delay=3 --sleep=3 --tries=3
--daemon

The queue:work Artisan command includes a --daemon option for forcing the queue worker to continue processing jobs without ever re-booting the framework. This results in a significant reduction of CPU usage when compared to the queue:listen command

总体来说,在 supervisor 中一般要加这个 option,可以节省 CPU 使用。

--quiet

不输出任何内容

--delay=3

一个任务失败后,延迟多长时间后再重试,单位是秒。这个值的设定我个人建议不要太短,因为一个任务失败(比如网络原因),重试时间太短可能会出现连续失败的情况。

--sleep=3

去 Redis 中拿任务的时候,发现没有任务,休息多长时间,单位是秒。这个值的设定要看你的任务是否紧急,如果是那种非常紧急的任务,不能等待太长时间。

--tries=3

定义失败任务最多重试次数。这个值的设定根据任务的重要程度来确定,一般 3 次比较适合。

创建任务

生成任务类

在你的应用程序中,队列的任务类都默认放在 app/Jobs 目录下。如果这个目录不存在,那当你运行 make:job Artisan 命令时目录就会被自动创建。你可以用以下的 Artisan 命令来生成一个新的队列任务:

php artisan make:job Demo

生成的类实现了 Illuminate\Contracts\Queue\ShouldQueue 接口,这意味着这个任务将会被推送到队列中,而不是同步执行。

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Facades\Log;

class Demo implements ShouldQueue
{
 use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

 public $param;
 /**
 * Create a new job instance.
 *
 * @return void
 */
 public function __construct($param = '')
 {
 $this->param = $param;
 }

 /**
 * Execute the job.
 *
 * @return void
 */
 public function handle()
 {
 Log::info('Hello, '.$this->param);
 }
}

控制器代码

public function queue_demo()
{
 $num = rand(1,999999999);
 // 这个任务将被分发到默认队列...
 DemoJob::dispatch($num);
}

开启队列

php artisan queue:work --queue=default

由于是本地,需要打开监听,当访问到接口时,就会触发队列中的任务

线上的话需要用到supervisor的配置

Supervisor 配置

安装 Supervisor

Supervisor 是一个 Linux 操作系统上的进程监控软件,它会在 queue:listen 或 queue:work 命令发生失败后自动重启它们。在 Ubuntu 安装 Supervisor,可以用以下命令:

sudo apt-get install supervisor

{tip} 如果自己手动配置 Supervisor 听起来有点难以应付,可以考虑使用 Laravel Forge,它能给你的 Laravel 项目自动安装与配置 Supervisor。

配置 Supervisor

Supervisor 的配置文件一般是放在 /etc/supervisor/conf.d 目录下。在这个目录中你可以创建任意数量的配置文件来要求 Supervisor 怎样监控你的进程。例如我们创建一个 laravel-worker.conf 来启动与监控一个 queue:work 进程:

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /home/forge/app.com/artisan queue:work sqs --sleep=3 --tries=3
autostart=true
autorestart=true
user=forge
numprocs=8
redirect_stderr=true
stdout_logfile=/home/forge/app.com/worker.log

这个例子里的 numprocs 命令会要求 Supervisor 运行并监控 8 个 queue:work 进程,并且在它们运行失败后重新启动。当然,你必须更改 command 命令的 queue:work sqs ,以显示你所选择的队列驱动。

启动 Supervisor 当这个配置文件被创建后,你需要更新 Supervisor 的配置,并用以下命令来启动该进程:

sudo supervisorctl reread

sudo supervisorctl update

sudo supervisorctl start laravel-worker:*

更多有关 Supervisor 的设置与使用,请参考 Supervisor 官方文档

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
PHP四舍五入精确小数位及取整
Jan 14 PHP
php删除指定目录的方法
Apr 03 PHP
PHP内核探索:哈希表碰撞攻击原理
Jul 31 PHP
php实现Session存储到Redis
Nov 11 PHP
php用户注册信息验证正则表达式
Nov 12 PHP
PHP获取二维数组中某一列的值集合
Dec 25 PHP
thinkphp项目部署到Linux服务器上报错“模板不存在”如何解决
Apr 27 PHP
thinkPHP简单遍历数组方法分析
May 16 PHP
Yii2如何批量添加数据
May 17 PHP
PHP实现接收二进制流转换成图片的方法
Jan 10 PHP
bindParam和bindValue的区别以及在Yii2中的使用详解
Mar 12 PHP
解决Laravel使用验证时跳转到首页的问题
Nov 17 PHP
PHP单文件上传原理及上传函数的封装操作示例
Sep 02 #PHP
PHP实现单文件、多个单文件、多文件上传函数的封装示例
Sep 02 #PHP
PHP 文件上传限制问题
Sep 01 #PHP
laravel框架模板之公共模板、继承、包含实现方法分析
Aug 30 #PHP
php中的钩子理解及应用实例分析
Aug 30 #PHP
Yii框架分页技术实例分析
Aug 30 #PHP
Laravel5.4简单实现app接口Api Token认证方法
Aug 29 #PHP
You might like
PHP中英混合字符串截取函数代码
2011/07/17 PHP
php实现telnet功能示例
2014/04/08 PHP
thinkPHP中分页用法实例分析
2015/12/26 PHP
PHP模拟http请求的方法详解
2016/11/09 PHP
php压缩文件夹最新版
2018/07/18 PHP
Javascript的一种模块模式
2010/09/08 Javascript
javaScript(JS)替换节点实现思路介绍
2013/04/17 Javascript
通过js获取div的background-image属性
2013/10/15 Javascript
angularjs学习笔记之简单介绍
2015/09/26 Javascript
轻松学习Javascript闭包函数
2015/12/15 Javascript
JavaScript面向对象程序设计教程
2016/03/29 Javascript
深入浅析JavaScript中with语句的理解
2016/05/12 Javascript
JS只能输入正整数的简单实例
2016/10/07 Javascript
JS表单提交验证、input(type=number) 去三角 刷新验证码
2017/06/21 Javascript
使用Vue的slot插槽分发父组件内容实现高度复用、更加灵活的组件(推荐)
2018/05/01 Javascript
vue2过滤器模糊查询方法
2018/09/16 Javascript
ES6 Set结构的应用实例分析
2019/06/26 Javascript
vue实现节点增删改功能
2019/09/26 Javascript
vue + node如何通过一个Txt文件批量生成MP3并压缩成Zip
2020/06/02 Javascript
Python使用cx_Oracle模块将oracle中数据导出到csv文件的方法
2015/05/16 Python
python安装numpy&amp;安装matplotlib&amp; scipy的教程
2017/11/02 Python
50行Python代码实现人脸检测功能
2018/01/23 Python
TensorFlow用expand_dim()来增加维度的方法
2018/07/26 Python
使用python判断你是青少年还是老年人
2018/11/29 Python
基于python 微信小程序之获取已存在模板消息列表
2019/08/05 Python
TensorFlow实现打印每一层的输出
2020/01/21 Python
解决pycharm中opencv-python导入cv2后无法自动补全的问题(不用作任何文件上的修改)
2020/03/05 Python
使用Matplotlib绘制不同颜色的带箭头的线实例
2020/04/17 Python
为什么在使用动态 SQL 语句时必须为低层数据库对象授予权限
2012/12/13 面试题
铭立家具面试题
2012/12/06 面试题
怎么写好自荐书
2014/03/02 职场文书
工商行政管理专业求职书
2014/05/23 职场文书
《童年》读后感(三篇)
2019/08/27 职场文书
浅谈怎么给Python添加类型标注
2021/06/08 Python
Python turtle编写简单的球类小游戏
2022/03/31 Python
云服务器部署 Web 项目的实现步骤
2022/06/28 Servers