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 相关文章推荐
ftp类(example.php)
Oct 09 PHP
php HandlerSocket的使用
May 02 PHP
解析strtr函数的效率问题
Jun 26 PHP
php防止站外远程提交表单的方法
Oct 20 PHP
ThinkPHP采用原生query实现关联查询left join实例
Dec 02 PHP
ThinkPHP自定义函数解决模板标签加减运算的方法
Jul 03 PHP
两种php给图片加水印的实现代码
Apr 18 PHP
Symfony2创建页面实例详解
Mar 18 PHP
thinkphp框架实现数据添加和显示功能
Jun 29 PHP
无需数据库在线投票调查php代码
Jul 20 PHP
php接口技术实例详解
Dec 07 PHP
PHP删除字符串中非字母数字字符方法总结
Jan 20 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中ob(Output Buffer 输出缓冲)函数使用方法
2007/07/21 PHP
PHP 修复未正常关闭的HTML标签实现代码(支持嵌套和就近闭合)
2012/06/07 PHP
PHP实现批量修改文件名的方法示例
2019/09/18 PHP
JS加载器如何动态加载外部js文件
2016/05/26 Javascript
AngularJS Ajax详解及示例代码
2016/08/17 Javascript
jQuery实用密码强度检测
2017/03/02 Javascript
Js中将Long转换成日期格式的实现方法
2018/06/05 Javascript
JS实现点击按钮可实现编辑功能
2018/07/03 Javascript
JavaScript笛卡尔积超简单实现算法示例
2018/07/30 Javascript
layui的table单击行勾选checkbox功能方法
2018/08/14 Javascript
微信小程序实现banner图轮播效果
2020/06/28 Javascript
js最实用string(字符串)类型的使用及截取与拼接详解
2019/04/26 Javascript
策略模式实现 Vue 动态表单验证的方法
2019/09/16 Javascript
微信小程序点击列表跳转到对应详情页过程解析
2019/09/26 Javascript
Python Web框架Tornado运行和部署
2020/10/19 Python
Python 专题二 条件语句和循环语句的基础知识
2017/03/19 Python
python实现感知器算法详解
2017/12/19 Python
Python代码块批量添加Tab缩进的方法
2018/06/25 Python
神经网络相关之基础概念的讲解
2018/12/29 Python
Python构建图像分类识别器的方法
2019/01/12 Python
Pandas库之DataFrame使用的学习笔记
2019/06/21 Python
windows下python虚拟环境virtualenv安装和使用详解
2019/07/16 Python
Python字符编码转码之GBK,UTF8互转
2020/02/09 Python
协程Python 中实现多任务耗资源最小的方式
2020/10/19 Python
python tqdm实现进度条的示例代码
2020/11/10 Python
CSS3 画基本图形,圆形、椭圆形、三角形等
2016/09/20 HTML / CSS
迪奥美国官网:Dior美国
2019/12/07 全球购物
Cocopanda波兰:购买化妆品、护肤品、护发和香水
2020/05/25 全球购物
幼儿园教育教学反思
2014/01/31 职场文书
商务经理岗位职责
2014/08/03 职场文书
城市规划应届生推荐信
2014/09/08 职场文书
护士工作心得体会
2016/01/25 职场文书
[有人@你]你有一封绿色倡议书,请查收!
2019/07/18 职场文书
PHP命令行与定时任务
2021/04/01 PHP
Unity连接MySQL并读取表格数据的实现代码
2021/06/20 MySQL
Oracle配置dblink访问PostgreSQL的操作方法
2022/03/21 PostgreSQL