Lumen开发:结合Redis实现消息队列(3)
4、运行队列监听器
开启任务监听器
Lumen包含了一个Artisan命令用来运行推送到队列的新任务。你可以使用queue:listen
命令运行监听器:
1 | php artisan queue:listen |
还可以指定监听器使用哪个队列连接:
1 | php artisan queue:listen connection |
注意一旦任务开始后,将会持续运行直到手动停止。你可以使用一个过程监视器如Supervisor来确保队列监听器没有停止运行。
队列优先级
你可以传递逗号分隔的队列连接列表到listen
任务来设置队列优先级:
1 | php artisan queue:listen --queue=high,low |
在本例中,high
队列上的任务总是在从low
队列移动任务之前被处理。
指定任务超时参数
你还可以设置每个任务允许运行的最大时间(以秒为单位):
1 | php artisan queue:listen --timeout=60 |
指定队列睡眠时间
此外,可以指定轮询新任务之前的等待时间(以秒为单位):
1 | php artisan queue:listen --sleep=5 |
需要注意的是队列只会在队列上没有任务时“睡眠”,如果存在多个有效任务,该队列会持续运行,从不睡眠。
4.1 Supervisor配置
Supervisor为Linux操作系统提供的进程监视器,将会在失败时自动重启queue:listen
或queue:work
命令,要在Ubuntu上安装Supervisor,使用如下命令:
1 | sudo apt-get install supervisor |
Supervisor配置文件通常存放在/etc/supervisor/conf.d
目录,在该目录中,可以创建多个配置文件指示Supervisor如何监视进程,例如,让我们创建一个开启并监视queue:work
进程的laravel-worker.conf
文件:
1 2 3 4 5 6 7 8 9 | [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 --daemon autostart=true autorestart=true user=forge numprocs=8 redirect_stderr=true stdout_logfile=/home/forge/app.com/worker.log |
在本例中,numprocs
指令让Supervisor运行8个queue:work
进程并监视它们,如果失败的话自动重启。配置文件创建好了之后,可以使用如下命令更新Supervisor配置并开启进程:
1 2 3 | sudo supervisorctl reread sudo supervisorctl update sudo supervisorctl start laravel-worker:* |
要了解更多关于Supervisor的使用和配置,查看Supervisor文档。此外,还可以使用Lumen Forge从web接口方便地自动配置和管理Supervisor配置。
4.2 后台队列监听器
Artisan命令queue:work
包含一个--daemon
选项来强制队列worker持续处理任务而不必重新启动框架。相较于queue:listen
命令该命令对CPU的使用有明显降低:
1 2 3 | php artisan queue:work connection --daemon php artisan queue:work connection --daemon --sleep=3 php artisan queue:work connection --daemon --sleep=3 --tries=3 |
正如你所看到的,queue:work
任务支持大多数queue:listen
中有效的选项。你可以使用php artisan help queue:work
任务来查看所有有效选项。
后台队列监听器编码考虑
后台队列worker在处理每个任务时不重启框架,因此,你要在任务完成之前释放资源,举个例子,如果你在使用GD库操作图片,那么就在完成时使用imagedestroy
释放内存。
类似的,数据库连接应该在后台长时间运行完成后断开,你可以使用DB::reconnect
方法确保获取了一个新的连接。
4.3 部署后台队列监听器
由于后台队列worker是常驻进程,不重启的话不会应用代码中的更改,所以,最简单的部署后台队列worker的方式是使用部署脚本重启所有worker,你可以通过在部署脚本中包含如下命令重启所有worker:
1 | php artisan queue:restart |
该命令会告诉所有队列worker在完成当前任务处理后重启以便没有任务被遗漏。
注意:这个命令依赖于缓存系统重启进度表,默认情况下,APC在CLI任务中无法正常工作,如果你在使用APC,需要在APC配置中添加
apc.enable_cli=1
。
5、处理失败任务
由于事情并不总是按照计划发展,有时候你的队列任务会失败。别担心,它发生在我们大多数人身上!Lumen包含了一个方便的方式来指定任务最大尝试执行次数,任务执行次数达到最大限制后,会被插入到failed_jobs
表,失败任务的名字可以通过配置文件config/queue.php
来配置。
要创建一个failed_jobs表的迁移,可以使用queue:failed-table命令:
1 | php artisan queue:failed-table |
运行队列监听器的时候,可以在queue:listen
命令上使用--tries
开关来指定任务最大可尝试执行次数:
1 | php artisan queue:listen connection-name --tries=3 |
5.1 失败任务事件
如果你想要注册一个队列任务失败时被调用的事件,可以使用Queue::failing
方法,该事件通过邮件或HipChat通知团队。举个例子,我么可以在Lumen自带的AppServiceProvider
中附件一个回调到该事件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <?php namespace App\Providers; use Queue; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider{ /** * 启动应用服务 * * @return void */ public function boot() { Queue::failing( function ( $connection , $job , $data ) { // Notify team of failing job... }); } /** * 注册服务提供者 * * @return void */ public function register() { // } } |
任务类的失败方法
想要更加细粒度的控制,可以在队列任务类上直接定义failed
方法,从而允许你在失败发生时执行指定动作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <?php namespace App\Jobs; use App\Jobs\Job; use Illuminate\Contracts\Mail\Mailer; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Bus\SelfHandling; use Illuminate\Contracts\Queue\ShouldQueue; class SendReminderEmail extends Job implements SelfHandling, ShouldQueue { use InteractsWithQueue, SerializesModels; /** * 执行任务 * * @param Mailer $mailer * @return void */ public function handle(Mailer $mailer ) { // } /** * 处理失败任务 * * @return void */ public function failed() { // Called when the job is failing... } } |
5.2 重试失败任务
要查看已插入到failed_jobs
数据表中的所有失败任务,可以使用Artisan命令queue:failed
:
1 | php artisan queue:failed |
该命令将会列出任务ID,连接,对列和失败时间,任务ID可用于重试失败任务,例如,要重试一个ID为5的失败任务,要用到下面的命令:
1 | php artisan queue:retry 5 |
如果你要删除一个失败任务,可以使用queue:forget
命令:
1 | php artisan queue:forget 5 |
要删除所有失败任务,可以使用queue:flush
命令:
1 | php artisan queue: flush |
参考:https://www.kancloud.cn/manual/lumen-docs/71329
相关:
《使用php轻框架-lumen搭建api服务》http://www.jianshu.com/p/bba4239c7c03
[ Lumen 5.1 文档 ] 更多特性 —— 队列:http://laravelacademy.org/post/469.html
Docker笔记二:Lumen + Redis:http://www.cnblogs.com/XiongMaoMengNan/p/6505621.html
Laravel 4.2 中队列服务(queue)的使用感受和踩到的坑:https://lvwenhan.com/laravel/395.html
Laravel中的队列处理:http://blog.csdn.net/u011816231/article/details/51745362
Laravel消息队列:http://www.jianshu.com/p/c808c5c5d439
supervisor配置lumen队列
1 2 3 4 5 6 7 8 9 | program:services-queue-supervisor] process_name=%(process_num)02d command=php / var /www/project/artisan queue:work --sleep=3 --daemon autostart= true autorestart= true numprocs=1 stdout_logfile=/ var /www/logs/queue_supervisor.log stderr_logfile=NONE user=nginx |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!