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 相关文章推荐
xml+php动态载入与分页
Oct 09 PHP
PHP令牌 Token改进版
Jul 18 PHP
IIS php环境配置PHP5 MySQL5 ZendOptimizer phpmyadmin安装与配置
Nov 18 PHP
解析PHP将对象转换成数组的方法(兼容多维数组类型)
Jun 21 PHP
基于PHP创建Cookie数组的详解
Jul 03 PHP
php合并js请求的例子
Nov 01 PHP
Codeigniter生成Excel文档的简单方法
Jun 12 PHP
PHP实现的购物车类实例
Jun 17 PHP
WordPress中自定义后台管理界面配色方案的小技巧
Dec 29 PHP
浅谈php中的访问修饰符private、protected、public的作用范围
Nov 20 PHP
php实现遍历文件夹的方法汇总
Mar 02 PHP
微信公众平台开发教程②微信端分享功能图文详解
Apr 10 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的无限分类实现想法~
2007/01/02 PHP
ThinkPHP与PHPExcel冲突解决方法
2011/08/08 PHP
PHP与MongoDB简介|安全|M+PHP应用实例详解
2013/06/17 PHP
php生成excel列序号代码实例
2013/12/24 PHP
php防止网站被刷新的方法汇总
2014/12/01 PHP
tp5.0框架隐藏index.php入口文件及模块和控制器的方法分析
2020/02/11 PHP
jquery获取焦点和失去焦点事件代码
2013/04/21 Javascript
js获取URL的参数的方法(getQueryString)示例
2013/09/29 Javascript
js二维数组排序的简单示例代码
2014/01/24 Javascript
node.js中的url.format方法使用说明
2014/12/10 Javascript
jQuery中innerHeight()方法用法实例
2015/01/19 Javascript
JavaScript学习笔记之JS事件对象
2015/01/22 Javascript
JQuery异步提交表单与文件上传功能示例
2017/01/12 Javascript
微信小程序 wx:for的使用实例详解
2017/04/27 Javascript
微信小程序用户自定义模版用法实例分析
2017/11/28 Javascript
微信小程序仿美团城市选择
2018/06/06 Javascript
详解Webpack-dev-server的proxy用法
2018/09/08 Javascript
Vue-Cli项目优化操作的实现
2019/10/27 Javascript
JS中类的静态方法,静态变量,实例方法,实例变量区别与用法实例分析
2020/03/14 Javascript
[01:02:46]VGJ.S vs NB 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
pycharm 主题theme设置调整仿sublime的方法
2018/05/23 Python
Python语言检测模块langid和langdetect的使用实例
2019/02/19 Python
Python序列对象与String类型内置方法详解
2019/10/22 Python
解决pycharm最左侧Tool Buttons显示不全的问题
2019/12/17 Python
浅析Python 多行匹配模式
2020/07/24 Python
CSS3 透明色 RGBA使用介绍
2013/08/06 HTML / CSS
HTML5+CSS3实现拖放(Drag and Drop)示例
2014/07/07 HTML / CSS
Canvas波浪花环的示例代码
2020/08/21 HTML / CSS
亚洲最大旅游体验平台:KKday
2017/10/21 全球购物
Fox Racing英国官网:越野摩托车和山地自行车服装
2020/02/26 全球购物
竞争性谈判邀请书
2014/02/06 职场文书
幼儿园毕业教师感言
2014/02/21 职场文书
运动会开幕式主持词
2014/03/28 职场文书
法定代表人授权委托书
2014/09/19 职场文书
建房合同协议书
2016/03/21 职场文书
python保存大型 .mat 数据文件报错超出 IO 限制的操作
2021/05/10 Python