Yii2 队列 shmilyzxt/yii2-queue 简单概述


Posted in PHP onAugust 02, 2017

shmilyzxt/yii2-queue 简单解释:

1.我用的yii2高级版,我们从配置开始看代码,这里我用的是mysql队列,首先配置文件,我把queue配置项写在根目录common\config\main-local.php下的 components数组下,更改一下数据库配置.复制composer安装后复制

vendor\shmilyzxt\yii2-queue\jobs\jobs.sql
vendor\shmilyzxt\yii2-queue\failed\failed.sql

2个sql文件到数据库中建立队列数据表和执行任务失败时的数据表.

2.推送任务开始语法:\Yii::$app->queue->pushOn(new SendMial(),['email'=>'49783121@qq.com','title'=>'test','content'=>'email test'],'email'); 我们到vendor\shmilyzxt\queue\queues\DatabaseQueue.php去看看代码,pushOn()方法写在了DatabaseQueue类的父类vendor\shmilyzxt\queue\base\Queue.php中:

//入队列
public function pushOn($job, $data = '', $queue = null)
 {
 //canPush 检查队列是否已达最大任务量
 if ($this->canPush()) { 
  //beforePush 入队列前的事件
  $this->trigger(self::EVENT_BEFORE_PUSH); 
  //入队列
  $ret = $this->push($job, $data, $queue);
  //afterPush 入队列后的事件
  $this->trigger(self::EVENT_AFTER_PUSH);
  return $ret;
 } else {
  throw new \Exception("max jobs number exceed! the max jobs number is {$this->maxJob}");
 }
 }

注释:这里最好去看看yii2 event事件类,http://www.digpage.com/event.html

关于入队列: $this->push($job, $data, $queue);,这里在配合queue类文件查看,相关函数跳转,处理一下数据记录到数据库中.(函数走向:getQueue()-->createPayload()-->pushToDatabase()),pushOn()最终返回数据插入数据库的结果,成功$ret是1.

3.后台运行命令处理队列,例:php ./yii worker/listen default 10 128 3 0 其中default是队列的名称,上面推送了一个email队列 应该改为email.

启动命令后,我们来看代码:首先执行:WorkerController控制器 actionListen方法,我们跟着代码进入到 vendor\shmilyzxt\queue\Worker.php -- listen方法中,这里其实就是一直在循环,执行操作队列的任务:

/**
 * 启用一个队列后台监听任务
 * @param Queue $queue
 * @param string $queueName 监听队列的名称(在pushon的时候把任务推送到哪个队列,则需要监听相应的队列才能获取任务)
 * @param int $attempt 队列任务失败尝试次数,0为不限制
 * @param int $memory 允许使用的最大内存
 * @param int $sleep 每次检测的时间间隔
 */
 public static function listen(Queue $queue, $queueName = 'default', $attempt = 10, $memory = 512, $sleep = 3, $delay = 0){
 while (true){
  try{
  //DatabaseQueue从数据库队列取出一个可用任务(实例),并且更新任务
  $job = $queue->pop($queueName);
  }catch (\Exception $e){
  throw $e;
  continue;
  }
  if($job instanceof Job){
  //判断执行错误的次数是否大于传入的执行次数
  if($attempt > 0 && $job->getAttempts() > $attempt){
   $job->failed();
  }else{
   try{
   //throw new \Exception("test failed");
   $job->execute();
   }catch (\Exception $e){
   //执行失败,判断是否被删除,重新入队
   if (! $job->isDeleted()) {
    $job->release($delay);
   }
   }
  }
  }else{
  self::sleep($sleep);
  }
  if (self::memoryExceeded($memory)) {
  self::stop();
  }
 }
 }

注释:在$queue->pop($queueName);vendor\shmilyzxt\queue\queues\DatabaseQueue.php方法内使用事务执行SQL,并且创建vendor\shmilyzxt\queue\jobs\DatabaseJob.php的实例

//取出一个任务
 public function pop($queue = null)
 {
 $queue = $this->getQueue($queue);
 if (!is_null($this->expire)) {
  //$this->releaseJobsThatHaveBeenReservedTooLong($queue);
 }
 $tran = $this->connector->beginTransaction();
 //判断是否有一个可用的任务需要执行
 if ($job = $this->getNextAvailableJob($queue)) {
  $this->markJobAsReserved($job->id);
  $tran->commit();
  $config = array_merge($this->jobEvent, [
  'class' => 'shmilyzxt\queue\jobs\DatabaseJob',
  'queue' => $queue,
  'job' => $job,
  'queueInstance' => $this,
  ]);
  return \Yii::createObject($config);
 }
 $tran->commit();
 return false;
 }

至于:$job->execute();是DatabaseJob继承父类Job执行的,顺着代码找下去是yii\base\Component trigger执行的事件,

/**
 * 执行任务
 */
public function execute()
{
 $this->trigger(self::EVENT_BEFORE_EXECUTE, new JobEvent(["job" => $this, 'payload' => $this->getPayload()]));//beforeExecute 执行任务之前的一个事件 在JobEvent中并没有什么可执行的代码
 $this->resolveAndFire();//真正执行的任务的方法
}
 /**
 * 真正任务执行方法(调用hander的handle方法)
 * @param array $payload
 * @return void
 */
 protected function resolveAndFire()
 {
  $payload = $this->getPayload();
  $payload = unserialize($payload); //反序列化数据
  $type = $payload['type'];
  $class = $payload['job'];
  if ($type == 'closure' && ($closure = (new Serializer())->unserialize($class[1])) instanceof \Closure) {
   $this->handler = $this->getHander($class[0]);
   $this->handler->closure = $closure;
   $this->handler->handle($this, $payload['data']);
  } else if ($type == 'classMethod') {
   $payload['job'][0]->$payload['job'][1]($this, $payload['data']);
  } else if ($type == 'staticMethod') {
   $payload['job'][0]::$payload['job'][1]($this, $payload['data']);
  } else {//执行的`SendMail`类的`handle($job,$data)`方法
   $this->handler = $this->getHander($class);
   $this->handler->handle($this, $payload['data']);
  }
  //执行完任务后删除
  if (!$this->isDeletedOrReleased()) {
   $this->delete();
  }
 }

最后到了执行的SendMail类的handle($job,$data),在这里就是推送到队列的对象和数据,接着就是我们的处理逻辑了.

public function handle($job,$data)
 {
  if($job->getAttempts() > 3){
   $this->failed($job);
  }
  $payload = $job->getPayload();
  echo '<pre>';print_r($payload);
  //$payload即任务的数据,你拿到任务数据后就可以执行发邮件了
  //TODO 发邮件
 }

总结

以上所述是小编给大家介绍的Yii2 队列 shmilyzxt/yii2-queue简介,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

PHP 相关文章推荐
PHP技术开发技巧分享
Mar 23 PHP
Window 7/XP 安装Apache 2.4与PHP 5.4 的过程详解
Jun 02 PHP
怎么在Windows系统中搭建php环境
Aug 31 PHP
php实现计数器方法小结
Jan 05 PHP
基于CakePHP实现的简单博客系统实例
Jun 28 PHP
10个php函数实用却不常见
Oct 13 PHP
php实现微信发红包
Dec 05 PHP
PHP命名空间namespace用法实例分析
Sep 27 PHP
PHP多维数组元素操作类的方法
Nov 14 PHP
PHP 类与构造函数解析
Feb 06 PHP
PHP与Web页面的交互示例详解二
Aug 04 PHP
PHP数组访问常用方法解析
Sep 05 PHP
基于win2003虚拟机中apache服务器的访问
Aug 01 #PHP
完美解决Thinkphp3.2中插入相同数据的问题
Aug 01 #PHP
TP3.2批量上传文件或图片 同名冲突问题的解决方法
Aug 01 #PHP
如何修改yii2.0自带的user表为其它的表
Aug 01 #PHP
修改yii2.0用户登录使用的user表为其它的表实现方法(推荐)
Aug 01 #PHP
Nginx下ThinkPHP5的配置方法详解
Aug 01 #PHP
PHP读取word文档的方法分析【基于COM组件】
Aug 01 #PHP
You might like
PHP入门之常量简介和系统常量
2014/05/12 PHP
php实现读取和写入tab分割的文件
2015/06/01 PHP
利用PHP脚本在Linux下用md5函数加密字符串的方法
2015/06/29 PHP
PHP输出多个元素的排列或组合的方法
2017/03/14 PHP
php实现的pdo公共类定义与用法示例
2017/07/19 PHP
在JavaScript中遭遇级联表达式陷阱
2007/03/08 Javascript
jquery 查找select ,并触发事件的实现代码
2011/03/30 Javascript
用nodejs写的一个简单项目打包工具
2013/05/11 NodeJs
js获取checkbox复选框选中的选项实例
2014/08/24 Javascript
Javascript让DEDECMS告别手写Tag
2014/09/01 Javascript
JavaScript利用HTML DOM进行文档操作的方法
2016/03/28 Javascript
浅谈jquery高级方法描述与应用
2016/10/04 Javascript
JavaScript canvas实现围绕旋转动画
2017/11/18 Javascript
ES6之Proxy的get方法详解
2019/10/11 Javascript
JavaScript canvas绘制折线图
2020/02/18 Javascript
vue实现点击按钮切换背景颜色的示例代码
2020/06/23 Javascript
Vue实现指令式动态追加小球动画组件的步骤
2020/12/18 Vue.js
vue中watch的用法汇总
2020/12/28 Vue.js
[03:02]2020完美世界城市挑战赛(秋季赛)总决赛回顾
2021/03/11 DOTA
python文件写入实例分析
2015/04/08 Python
Ubuntu下安装PyV8
2016/03/13 Python
利用python修改json文件的value方法
2018/12/31 Python
python3转换code128条形码的方法
2019/04/17 Python
python scrapy爬虫代码及填坑
2019/08/12 Python
Python爬虫过程解析之多线程获取小米应用商店数据
2020/11/14 Python
CSS3制作日历实现代码
2012/01/21 HTML / CSS
Java面试笔试题大全
2016/11/23 面试题
计算机专业个人简短的自我评价
2013/10/23 职场文书
什么样的创业计划书可行性高?
2014/02/01 职场文书
20年同学聚会邀请函
2014/02/04 职场文书
《秋姑娘的信》教学反思
2014/02/28 职场文书
婚纱摄影师求职信
2014/03/07 职场文书
初中作文评语大全
2014/04/23 职场文书
卫生厅领导班子党的群众路线教育实践活动整改措施
2014/09/20 职场文书
镇班子对照检查材料思想汇报
2014/09/24 职场文书
Python 操作pdf pdfplumber读取PDF写入Exce
2022/08/14 Python