深入了解laravel消费队列的两种工作模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wjc19911118/article/details/79408739

由来

一直在用laravel的Queue, 并且最近使用中也遇到一些问题,急迫的想搞清楚Laravel中的Queue到底是如何跑起来的 大家都知道Queue的运行有两种模式,一种是Wok, 一种是Listen, 在看过的博客中讲到的都不是很深入,大部分都是重复的Copy, 没有特别详细的讲解,知其然,而不知所以然,对于喜欢为Why的Coder来说很痛苦,于是就有了这篇文章,希望对您能有帮助

辅助工具

  1. xhprof, xhgui
  2. socketLog

宏观上分模块理解Queue消费的工作过程

下面我将一个完整的消费过程分为以下步骤理解,以及详细的陪图说明

  1. 命令行初始化模块
  2. 消费队列命令运行模块
  3. 任务的存储与操作
  4. 唤起执行任务的模块
  5. 具体任务执行模块

下面是一张UML图像,我把上面的5个模块中用到的重要的类都画了下来

在线浏览地址 点击链接

queue work flow

下面是一张类函数调用堆栈图,时序图太长画出来也不大好看

这里写图片描述

微观理解Listener VS Worker的区别

几种运行模式

  1. queue:work || queue:work --once 默认只执行一次队列请求, 当请求执行完成后就终止;
  2. queue:listen 监听队列请求, 只要运行着, 就能一直接受请求, 除非手动终止;
  3. queue:work --daemon 同 listen 一样, 只要运行着, 就能一直接受请求, 不一样的地方是在这个运行模式下, 当新的请求到来的时候, 不重新加载整个框架, 而是直接 fire 动作, 当更新代码的时候, 需要停止, 然后重新启动, 这样修改的代码才能起作用

Laravel5.3之前和之后对Worker的timeout有改动,>=5.3的version Work模式也支持了超时检测

相同点

  1. 最终都是执行的work
    <5.3 -> queue:work %s --queue=%s --delay=%s --memory=%s --sleep=%s --tries=%s
    >=5.3 -> queue:work %s --once --queue=%s --delay=%s --memory=%s --sleep=%s --tries=%s

下面的图片中可以看到, work只是执行了一次WorkCommand,然后循环处理每个任务, listen是用ListenCommand作为一个入口或者叫包装器,实际里面真正执行的还是work once

work

  • work

listen

  • listen

不同点

  1. Listen 方式使用的是Process实例去循环的执行Work Once, 所以你修改的Job代码会被从新加载,因为Listen的消费是单独开启独立的进程去消费的,当然浪费性能有进程开销
  2. Work 方式是while(true), 在当前的进程中去处理任务, 修改的代码不会生效
  3. Work的超时机制,在Laravel<=5.2前Work是不支持超时参数的,在Laravel>=5.3起,Work的daemon模式也开始支持超时机制了,这种机制使用的时钟 pcntl_alarm机制,时间到达后出发信号执行kill进程的操作,这种模式开启的要求是 version_compare(PHP_VERSION, '7.1.0') >= 0 && extension_loaded('pcntl')
  4. Listen的超时机制, 只要进程运行着就会自动检测
function wait(){
    ...
    do {
        $this->checkTimeout();
        ...
    } while ($running);
    ...
}   

使用流程图来描述一个任务的执行过程

Created with Raphaël 2.1.2 Start WorkCommand->runWorker Work->pop Work->getNextJob Worker->process 是否达到最大执行次数? Worker->logFailedJob failer->log job->delete job->failed this->raiseFailedJobEvent End RedisJob->fire CallQueuedHandler->call 是否执行异常,或超时? 任务是否被删除了? job->release (从新发布任务,并且尝试次数+1) job->delete (删除任务) RedisQueue->deleteReserved yes no yes no yes no

这里写图片描述

再来说下redis中的任务是在何时被删除的,如何删除的

这里写图片描述

当一个任务被lpop弹出之后,同时会将该认为添加到这个名字的队列中[当前队列名+:reserved],如上图,
在执行过程中如果任务在指定时间没有错误的正确执行完毕,那么这个任务会自动调用deleteReserved销毁, 假如执行有异常或者超时了,那么要判断任务的最大执行次数是否达到,没达到则再次release到队列中同时尝试次数加一,如果达到最大执行次数则执行执行失败,并将信息记录到数据库中.当然pop出消息前,还有一个步骤就是合并reserved,delayed的任务到队列中

猜你喜欢

转载自blog.csdn.net/wjc19911118/article/details/79408739
今日推荐