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函数array_merge用法一例(合并同类数组)
Feb 03 PHP
关于PHP自动判断字符集并转码的详解
Jun 26 PHP
php json与xml序列化/反序列化
Oct 28 PHP
php使用多个进程同时控制文件读写示例
Feb 28 PHP
php安装swoole扩展的方法
Mar 19 PHP
PHP调试的强悍利器之PHPDBG
Feb 22 PHP
简单介绍PHP非阻塞模式
Mar 03 PHP
PHP5.2中PDO的简单使用方法
Mar 25 PHP
PHP7扩展开发教程之Hello World实现方法示例
Aug 03 PHP
总结PHP代码规范、流程规范、git规范
Jun 18 PHP
PHP session垃圾回收机制实例分析
Jun 28 PHP
50个优秀经典PHP算法大集合 附源码
Aug 26 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
用Simple Excel导出xls实现方法
2012/12/06 PHP
修改PHP脚本使WordPress拦截垃圾评论的方法示例
2015/12/10 PHP
PHP+sqlite数据库操作示例(创建/打开/插入/检索)
2016/05/26 PHP
yii2安装详细流程
2018/05/23 PHP
jQuery使用手册之三 CSS操作
2007/03/24 Javascript
Javascript中Eval函数的使用说明
2008/10/11 Javascript
跟着JQuery API学Jquery 之二 属性
2010/04/09 Javascript
JavaScript toFixed() 方法
2010/04/15 Javascript
动态加载图片路径 保持JavaScript控件的相对独立性
2010/09/03 Javascript
表单序列化与jq中的serialize使用示例
2014/02/21 Javascript
JS实现可缩放、拖动、关闭和最小化的浮动窗口完整实例
2015/03/04 Javascript
AngularJS基础 ng-model-options 指令简单示例
2016/08/02 Javascript
jQuery网页定位导航特效实现方法
2016/12/19 Javascript
深入理解js中的加载事件
2017/02/08 Javascript
jQuery移除或禁用html元素点击事件常用方法小结
2017/02/10 Javascript
利用node.js搭建简单web服务器的方法教程
2017/02/20 Javascript
js实现楼层导航功能
2017/02/23 Javascript
详解webpack + vue + node 打造单页面(入门篇)
2017/09/23 Javascript
js 中rewrap-ajax.js插件实例代码
2017/10/20 Javascript
javascript之分片上传,断点续传的实际项目实现详解
2019/09/05 Javascript
vue vant Area组件使用详解
2019/12/09 Javascript
video.js添加自定义组件的方法
2020/12/09 Javascript
Python抓取手机号归属地信息示例代码
2016/11/28 Python
简单谈谈python基本数据类型
2018/09/26 Python
PyCharm配置mongo插件的方法
2018/11/30 Python
python 利用toapi库自动生成api
2020/10/19 Python
雅诗兰黛加拿大官网:Estee Lauder加拿大
2019/07/31 全球购物
GWT的应用有哪两种部署模式
2012/12/21 面试题
村官工作鉴定评语
2014/01/27 职场文书
模范教师事迹材料
2014/02/10 职场文书
售前工程师职业生涯规划
2014/03/02 职场文书
环保宣传标语
2014/06/12 职场文书
2014党员自我评议表范文
2014/09/20 职场文书
处级领导干部四风问题自我剖析材料
2014/09/29 职场文书
2014年客服工作总结与计划
2014/12/09 职场文书
心灵点滴观后感
2015/06/02 职场文书