源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

浅谈Laravel队列实现原理解决问题记录

  • 时间:2021-04-25 08:48 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:浅谈Laravel队列实现原理解决问题记录
[b]问题[/b] 公司项目使用Laravel的开发的两个项目在同一个测试服务器部署,公用同一个redis。在使用laravel中的队列时,产生冲突干扰。 [b]查找问题原因[/b] 在laravel 队列的操作类[code]Illuminate\Queue\RedisQueue.php[/code]中可以看到[code]pushRaw()[/code]方法:
// 将一任务推入队列中
public function pushRaw($payload, $queue = null, array $options = [])
  {
    $this->getConnection()->rpush($this->getQueue($queue), $payload);

    return Arr::get(json_decode($payload, true), 'id');
  }
从该方法中可以看出Lrarvel队列的redis实现是通过list结构实现的,[code]rpush(key, value)[/code]是将value推入键值为key的redis队列,key的值则是通过[code]$this->getQueue($queue) [/code]获取到的
protected function getQueue($queue)
  {
    return 'queues:'.($queue ?: $this->default);
  }
所以的redis中list中的key是[code] 'queues:'.($queue ?: $this->default);[/code]拼接的,[code]$this->default [/code]的值是 [code]RedisQueue [/code]实例化的时候从[code]config\queue.php[/code]配置中加载的[code] 'queue' => 'default'[/code],$queue 是添加队列时[code]$this->dispatch( new jobClass()->onQueue($queue) )[/code]传入的。
// config\queue.php 文件中的redis配置部分
'redis' => [
      'driver'   => 'redis',
      'connection' => 'default',
      'queue'   => 'default',
      'expire'   => 60,
    ],
至此,两个项目的队列冲突原因就找到了。因为redis队列配置中 [code]'queue' => 'default' [/code]都使用的默认的default,所以当共用redis时,默认的队列list 都是'queue:default',所以导致了冲突。 因为队列监听 监听的队列名称是由 --queue参数决定的,如果不传就是我们上面设置的默认值,若传了就会根据传入的队列名从前往后优先依次处理,具体见代码[code]Illuminate\Queue\Worker.php[/code]中:
protected function getNextJob($connection, $queue)
  {
    if (is_null($queue)) {
      return $connection->pop();
    }

    foreach (explode(',', $queue) as $queue) {
      if (! is_null($job = $connection->pop($queue))) {
        return $job;
      }
    }
  }
$queue就是--queue=传入的参数,当 $queue不存在是直接调用[code]$connection->pop()[/code]当参数存在时会将参数解析,优先处理排在前面的队列名称,将队列名称传入[code]pop($queue), pop()[/code]会尝试从指定队列或默认队列中获取队列任务
// Illuminate\Queue\RedisQueue.php
public function pop($queue = null)
  {
    $original = $queue ?: $this->default;

    $queue = $this->getQueue($queue);

    if (! is_null($this->expire)) {
      $this->migrateAllExpiredJobs($queue);
    }

    $job = $this->getConnection()->lpop($queue);

    if (! is_null($job)) {
      $this->getConnection()->zadd($queue.':reserved', $this->getTime() + $this->expire, $job);

      return new RedisJob($this->container, $this, $job, $original);
    }
  }

至此搞清了队列执行的原理。 [b]解决方法[/b] 将queue的配置文件中默认队列修改为不同的名称,比如: 'queue' => laravel1','queue' => laravel2'。 队列监听[code] php artisan queue:listen redis --queue=laravel1,syncExpress[/code] [b]最后[/b] 遇到问题,莫要病急乱投医。从代码入手,分析理解实现原理,找对点,解决方法也许很简单,希望对大家的学习有所帮助,也希望大家多多支持编程素材网。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部