Laravel入坑指南(11)——列队
很高兴,我们来到了Laravel入坑指南的第11篇。这一系列的文章已经接近尾声了,在这一节里面,我们一起讨论列队的用法。
列队,顾名思义,将需要处理的任务一个一个排好队,等待处理程序来处理。这机的列队机制,适用于需要异步处理的任务。
所以在这里,我们首先需要关注三个问题:谁来投递任务?将任务投递到哪里?谁来处理任务?
1、谁来投递任务?
在Laravel里,任务的投递和处理,都是由JOB类负责的。而且哪个JOB类投递的任务,就由那个JOB类进行处理(划重点)。首先,执行以下命令,就可以创建自己的JOB类:
php artisan make:job ProcessMyJob
这时,就会创建出/app/Jobs/ProcessMyJob.php。在这个类中,有一个构造函数,以及一个handle参数。构造函数的参数,就是分发任务时指定的参数,在获取任务实例化JOB时,就将列队中的任务参数传递进来;handle函数则是处理函数。
有了个这JOB类之后,我们可以在我们需要投递任务的地方(比如某个Controller里)进行投递:
//投递到默认列队,默认列队队名由配置文件决定,一般叫作default
ProcessMyJob::dispatch("参数"); //投递到名字为default2的列队
ProcessMyJob::dispatch("参数")->onQueue("myqueue");
现在问题来了,默认列队和名为myqueue的列队分别在哪里呢?
2、将任务投递到哪里?
关于这个问题,取决于配置文件/config/queue.php。在这个配置文件中,我们需要关注两个配置项:default和connections。
2.1 connections
'connections' => [
'sync' => [
'driver' => 'sync',
],
'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,
],
'beanstalkd' => [
'driver' => 'beanstalkd',
'host' => 'localhost',
'queue' => 'default',
'retry_after' => 90,
'block_for' => 0,
],
'sqs' => [
'driver' => 'sqs',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
'queue' => env('SQS_QUEUE', 'your-queue-name'),
'region' => env('AWS_REGION', 'us-east-1'),
],
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'block_for' => null,
],
],
这个配置项,让Laravel可以用同步、数据库、beanstalkd、亚马逊sql以及redis的方法来保存列队数据。当然,博主个人建议用redis来进行存储,所以下面所有的示例也会以redis作为例子进行讨论。我们在第6节中,已经配置完redis。如果还不明白的同学,请返回查看第6节。
根据上面所示connections配置项中,我们只需在/.evn文件中添加一个配置项:
REDIS_QUEUE=default
这一项就是指定上面所说的默认列队名字。当任务投递时没有指定名字,就会投递到这个名下的列队中。
2.2 default
这一项则是指定了名为default的列队,用哪种方式保存列队数据。因为上面的例子中,我们要把任务投递到名字为myqueue的列队中,所以我们还需要一个名为myqueue的列队。所以我们的配置如下:

在/.env配置文件中QUEUE_CONNECTION的值为redis:
QUEUE_CONNECTION=redis
到这里,我们知道任务由谁投递的,任务保存在哪里。那么在指定的地方投递完任务后,由谁调用JOB的handle函数,对任务进行处理呢?就是我们接下来关注的重点。
3、谁来处理任务?
在这里,我们需要操作系统长驻进程,一直监视着列队是否有任务要处理。所以我们还是离不开php的命令行。我们可以用以下方式启动监视进程:
#启动对所有列队的监听
php artisan queue:work #启动对default和myqueue的监听,default列队的优先级会高于myqueue的优先级
php artisan queue:work --queue=default,myqueue #在redis连接上启动对email列队的监听
#这种情况就不需要在配置文件中写email列队的配置项
php artisan queue:work redis --queue=email #列队清空后就退出
php artisan queue:work --stop-when-empty #启动两个监听进程,两个列队没有优先级关系
php artisan queue:work --queue=default
php artisan queue:work --queue=myqueue
被监听的列队,一旦有任务存在,监听进程就会实例化对应的JOB类,并调用handle函数进行处理。
4、万一监听进程挂了,怎么办?
为了解决这个问题,官方文档介绍了可以用Linux下的supervisor进行进程守护。现在让我们简单探讨
在CentOS下安装supervisor只需要执行:
yum install supervisor
安装完成后在就会创建出/etc/supervisord.conf配置文件和/etc/supervisord.d目录。其中,配置文件中有以下配置项:
[include]
files = supervisord.d/*.ini
所有的进程守护配置文件都存放在/etc/supervisord.d路径中。
安装完成后,我们需要创建启动脚本/etc/init.d/supervisor
#!/bin/sh # Source init functions
. /etc/rc.d/init.d/functions prog="supervisord" prefix="/usr/local"
exec_prefix="${prefix}"
prog_bin="${exec_prefix}/bin/supervisord"
PIDFILE="/var/run/$prog.pid" start()
{
echo -n $"Starting $prog: "
daemon $prog_bin -c /etc/supervisord.conf --pidfile $PIDFILE
[ -f $PIDFILE ] && success $"$prog startup" || failure $"$prog startup"
echo
} stop()
{
echo -n $"Shutting down $prog: "
[ -f $PIDFILE ] && killproc $prog || success $"$prog shutdown"
echo
} case "$1" in start)
start
;; stop)
stop
;; status)
status $prog
;; restart)
stop
start
;; *)
echo "Usage: $0 {start|stop|restart|status}"
;; esac
接下来,让我们进行一下测试,看看supervisor是否有效。创建一个配置文件:
/etc/supervisord.d/myqueue.ini
[program:myqueue]
process_name=%(program_name)s_%(process_num)02d
command=php /www/wwwroot/default/artisan queue:work
autostart=true
autorestart=true
numprocs=4
redirect_stderr=true
stdout_logfile=/tmp/test.out.log
创建完成后,执行
/etc/init.d/supervisor restart
会发现我们的列队监视进程已经启动,并且在我们kill掉进程时会自动重启。
到这里,我们列队的话题大功告成。
最后我们关注上一节遗留下的最后一个问题,关于事件Listener处理。如里我们需要以列队进行事件的处理,我们只需要让侦听器实现ShouldQueue接口即可:
<?php
namespace App\Listeners; use Illuminate\Contracts\Queue\ShouldQueue; class MyListener implements ShouldQueue
{
/**
* 任务将被推送到的连接名称.
*
* @var string|null
*/
public $connection = 'redis'; /**
* 任务将被推送到的列队名称.
*
* @var string|null
*/
public $queue = 'queue_name'; /**
* 任务被处理之前的延迟时间(秒)
*
* @var int
*/
public $delay = 60;
}
--------------------------- 我是可爱的分割线 ----------------------------
最后博主借地宣传一下,漳州编程小组招新了,这是一个面向漳州青少年信息学/软件设计的学习小组,有意向的同学点击链接,联系我吧。
Laravel入坑指南(11)——列队的更多相关文章
- electron入坑指南
electron入坑指南 简介 electron 实际集成chrome浏览器和node环境, 运行你写的网页 app 基本目录结构 index.html 名称可以不是index, 这个文件与普通网页的 ...
- C语言入坑指南-被遗忘的初始化
前言 什么是初始化?为什么要初始化?静态变量和局部变量的初始化又有什么区别?实际应用中应该怎么做?本文将一一回答这些问题. 什么是初始化 初始化指的是对数据对象或者变量赋予初始值.例如: int va ...
- Elasticsearch入坑指南之RESTful API
Elasticsearch入坑指南之RESTful API Tags:Elasticsearch ES为开发者提供了非常丰富的基于Http协议的Rest API,通过简单的Rest请求,就可以实现非常 ...
- ElasticSearch入坑指南之概述及安装
---恢复内容开始--- ElasticSearch入坑指南之概述及安装 了解ElasticSearch ElasticSearch(简称ES)基于Lucene的分布式全文检索引擎.使用ES可以实现近 ...
- eclipse中导入外部包却无法查看对应源码或Javadoc的入坑指南
eclipse中导入外部包却无法查看对应源码或Javadoc的 入坑指南 出现这个错误的原因是,你虽然导入了.jar包,但没有配置对应的Javadoc或源码路径,所以在编辑器中无法查看源 码和对应AP ...
- Rust入坑指南:核心概念
如果说前面的坑我们一直在用小铲子挖的话,那么今天的坑就是用挖掘机挖的. 今天要介绍的是Rust的一个核心概念:Ownership.全文将分为什么是Ownership以及Ownership的传递类型两部 ...
- Rust入坑指南:鳞次栉比
很久没有挖Rust的坑啦,今天来挖一些排列整齐的坑.没错,就是要介绍一些集合类型的数据类型."鳞次栉比"这个标题是不是显得很有文化? 在Rust入坑指南:常规套路一文中我们已经介绍 ...
- Rust入坑指南:亡羊补牢
如果你已经开始学习Rust,相信你已经体会过Rust编译器的强大.它可以帮助你避免程序中的大部分错误,但是编译器也不是万能的,如果程序写的不恰当,还是会发生错误,让程序崩溃.所以今天我们就来聊一聊Ru ...
- Rust入坑指南:朝生暮死
今天想和大家一起把我们之前挖的坑再刨深一些.在Java中,一个对象能存活多久全靠JVM来决定,程序员并不需要去关心对象的生命周期,但是在Rust中就大不相同,一个对象从生到死我们都需要掌握的很清楚. ...
- Rust入坑指南:齐头并进(上)
我们知道,如今CPU的计算能力已经非常强大,其速度比内存要高出许多个数量级.为了充分利用CPU资源,多数编程语言都提供了并发编程的能力,Rust也不例外. 聊到并发,就离不开多进程和多线程这两个概念. ...
随机推荐
- 【SHELL】百分比进度指示,原地踏步
百分比进度指示,原地踏步效果实现主要利用退格'\b',同行'\c' #!/bin/bash function percentage_progress() { progress=$(($1*100/$2 ...
- Qt5.9 UI设计(一)——在win10系统上安装Qt5.9
安装环境 win10 系统 Qt5.9.0 版本 官方下载地址 可以从官方网站获取:https://www.qt.io/zh-cn/ 现在的安装包跟以前的有些区别,加上网络比较慢,我这里演示的是Qt5 ...
- [转帖]Linux-文本处理三剑客grep详解
https://developer.aliyun.com/article/885611?spm=a2c6h.24874632.expert-profile.311.7c46cfe9h5DxWK 简介: ...
- [转帖]总结:记一次K8S容器OOM案例
一.背景 最近遇到个现象,hubble-api-open组件过段时间会内容占满,从而被K8S强制重启. 让我困惑的是,已经设置了-XX:MaxRAMPercentage=75.0,我觉得留有了一定的空 ...
- JVM内存学习 2.0
先说一下结果 1. Linux的内存分配是惰性分配的. APP申明了 kernel并不会立即进行初始化和使用. 2. JVM的内存主要分为, 堆区, 非堆区, 以及jvm使用的其他内存. 比如直接内存 ...
- 记windows自定义bat脚本自启动
自定义 Windows 启动脚本简化版 在本指南中,我们将使用一个简化的批处理文件(.bat)来演示如何创建自定义的 Windows 启动脚本.以下是一个基本的模板,您只需根据需要在 :begin 部 ...
- 没有虚拟DOM版本的vue(Vue Vapor)
前言 随着Svelte和SolidJS的流行,无虚拟DOM模式逐渐开始火了起来.vue也推出了无虚拟DOM模式的版本,就是我们今天要讲的Vue Vapor. 什么是Vue Vapor Vue Vapo ...
- 行云部署成长之路--慢SQL优化之旅 | 京东云技术团队
当项目的SQL查询慢得像蜗牛爬行时,用户的耐心也在一点点被消耗,作为研发,我们可不想看到这样的事.这篇文章将结合行云部署项目的实践经验,带你走进SQL优化的奇妙世界,一起探索如何让那些龟速的查询飞 ...
- js中的宏任务和微任务详细讲解
微任务有哪些 Promise await和async 宏任务有哪些 setTimeout setInterval DOM事件 AJAX请求 看下面的代码 <script> console. ...
- GitHub要求2FA?不慌,有它们帮你
近日,GitHub宣布,到 2023 年底,所有用户都必须要启用双因素身份验证 (2FA),不能只用密码啦. 正如GitHub的首席安全官Mike Hanley所指出的那样,保护开发者账号是确保软件供 ...