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 相关文章推荐
JAVA/JSP学习系列之七
Oct 09 PHP
PHP防范SQL注入的具体方法详解(测试通过)
May 09 PHP
纯php生成随机密码
Oct 30 PHP
windows平台中配置nginx+php环境
Dec 06 PHP
php创建桌面快捷方式实现方法
Dec 31 PHP
php微信公众账号开发之前五个坑(一)
Sep 18 PHP
ThinkPHP实现生成和校验验证码功能
Apr 28 PHP
php模仿qq空间或朋友圈发布动态、评论动态、回复评论、删除动态或评论的功能(中)
Jun 11 PHP
阿里云PHP SMS短信服务验证码发送方法
Jul 11 PHP
PHP ADODB实现事务处理功能示例
May 25 PHP
asp函数split()对应php函数explode()
Feb 27 PHP
laravel-admin解决表单select联动时,编辑默认没选上的问题
Sep 30 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调用Oracle存储过程
2006/10/09 PHP
php4的session功能评述(二)
2006/10/09 PHP
PHP实现对站点内容外部链接的过滤方法
2014/09/10 PHP
Mac下关于PHP环境和扩展的安装详解
2019/10/17 PHP
jquery nth-child()选择器的简单应用
2010/07/10 Javascript
9行javascript代码获取QQ群成员具体实现
2013/10/16 Javascript
jquery实现pager控件示例
2014/04/09 Javascript
jQuery遍历之next()、nextAll()方法使用实例
2014/11/08 Javascript
javascript基本包装类型介绍
2015/04/10 Javascript
angularjs客户端实现压缩图片文件并上传实例
2015/07/06 Javascript
在Html中使用Requirejs进行模块化开发实例详解
2016/04/15 Javascript
基于Turn.js 实现翻书效果实例解析
2016/06/20 Javascript
JS基于构造函数实现的菜单滑动显隐效果【测试可用】
2016/06/21 Javascript
使用clipboard.js实现复制功能的示例代码
2017/10/16 Javascript
微信小程序模板和模块化用法实例分析
2017/11/28 Javascript
react-router v4如何使用history控制路由跳转详解
2018/01/09 Javascript
在Vue.js中使用TypeScript的方法
2020/03/19 Javascript
微信公众号中的JSSDK接入及invalid signature等常见错误问题分析(全面解析)
2020/04/11 Javascript
JQuery+drag.js上传图片并且实现图片拖曳
2020/11/18 jQuery
Python中zfill()方法的使用教程
2015/05/20 Python
Python中在for循环中嵌套使用if和else语句的技巧
2016/06/20 Python
Pycharm如何运行.py文件的方法步骤
2020/03/03 Python
使用Keras中的ImageDataGenerator进行批次读图方式
2020/06/17 Python
从python读取sql的实例方法
2020/07/21 Python
详解Python中第三方库Faker
2020/09/25 Python
python爬虫快速响应服务器的做法
2020/11/24 Python
AmazeUI的JS表单验证框架实战示例分享
2020/08/21 HTML / CSS
linux面试题参考答案(7)
2012/10/29 面试题
MYSQL基础面试题
2012/05/13 面试题
护理自我鉴定范文
2013/10/06 职场文书
跳槽求职信范文
2014/05/26 职场文书
八年级上册语文教学计划
2015/01/22 职场文书
公司职员入党自传书
2015/06/26 职场文书
500字作文之关于爸爸
2019/11/14 职场文书
详解Java实践之适配器模式
2021/06/18 Java/Android
MySQL8.0 Undo Tablespace管理详解
2022/06/16 MySQL