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

作者:Dr點燃 时间:2024-06-05 15:39:54 

问题

公司项目使用Laravel的开发的两个项目在同一个测试服务器部署,公用同一个redis。在使用laravel中的队列时,产生冲突干扰。

查找问题原因

在laravel 队列的操作类Illuminate\Queue\RedisQueue.php中可以看到pushRaw()方法:


// 将一任务推入队列中
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结构实现的,rpush(key, value)是将value推入键值为key的redis队列,key的值则是通过$this->getQueue($queue) 获取到的


protected function getQueue($queue)
 {
   return 'queues:'.($queue ?: $this->default);
 }

所以的redis中list中的key是 'queues:'.($queue ?: $this->default);拼接的,$this->default 的值是 RedisQueue 实例化的时候从config\queue.php配置中加载的 'queue' => 'default',$queue 是添加队列时$this->dispatch( new jobClass()->onQueue($queue) )传入的。


// config\queue.php 文件中的redis配置部分
'redis' => [
     'driver'   => 'redis',
     'connection' => 'default',
     'queue'   => 'default',
     'expire'   => 60,
   ],

至此,两个项目的队列冲突原因就找到了。因为redis队列配置中 'queue' => 'default' 都使用的默认的default,所以当共用redis时,默认的队列list 都是'queue:default',所以导致了冲突。

因为队列监听 监听的队列名称是由 --queue参数决定的,如果不传就是我们上面设置的默认值,若传了就会根据传入的队列名从前往后优先依次处理,具体见代码Illuminate\Queue\Worker.php中:


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不存在是直接调用$connection->pop()当参数存在时会将参数解析,优先处理排在前面的队列名称,将队列名称传入pop($queue), pop()会尝试从指定队列或默认队列中获取队列任务


// 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);
   }
 }

至此搞清了队列执行的原理。

解决方法

将queue的配置文件中默认队列修改为不同的名称,比如: 'queue' => laravel1','queue' => laravel2'。

队列监听 php artisan queue:listen redis --queue=laravel1,syncExpress

最后

遇到问题,莫要病急乱投医。从代码入手,分析理解实现原理,找对点,解决方法也许很简单,希望对大家的学习有所帮助,也希望大家多多支持asp之家。

来源:http://www.jianshu.com/p/8e54bd3d7159?utm_source=tuicool&utm_medium=referral

标签:Laravel,队列
0
投稿

猜你喜欢

  • 35个JS中实用工具函数的代码分享

    2024-05-03 15:08:25
  • 利用python实现命令行有道词典的方法示例

    2021-03-24 06:32:16
  • Python中的np.random.seed()随机数种子问题及解决方法

    2023-01-15 20:14:02
  • Ubuntu 18.04.4安装mysql的过程详解 亲测可用

    2024-01-15 18:46:21
  • CentOS6.9下mysql 5.7.17安装配置方法图文教程

    2024-01-23 12:26:03
  • MYSQL实现添加购物车时防止重复添加示例代码

    2024-01-15 01:44:15
  • Python中getpass模块无回显输入源码解析

    2022-05-02 03:58:28
  • javascript for-in有序遍历json数据并探讨各个浏览器差异

    2024-05-25 15:18:17
  • python实现定时自动备份文件到其他主机的实例代码

    2023-04-26 09:30:52
  • Python如何截图保存的三种方法(小结)

    2023-08-24 22:17:19
  • 利用Python matplotlib绘制风能玫瑰图

    2023-10-12 23:07:24
  • python设置Pyplot的动态rc参数、绘图的填充

    2023-12-15 22:52:29
  • Windows下python3.7安装教程

    2023-02-16 16:39:11
  • Python中BeautifulSoup通过查找Id获取元素信息

    2022-12-22 22:08:59
  • python使用itchat库实现微信机器人(好友聊天、群聊天)

    2023-07-12 10:38:39
  • 如何在Python项目中引入日志

    2023-01-25 15:10:53
  • MySQL 数据库语句优化的原则

    2010-01-20 10:11:00
  • Python Gitlab Api 使用方法

    2021-03-11 16:30:11
  • Flask框架 CSRF 保护实现方法详解

    2021-07-05 08:27:05
  • PHP 动态随机生成验证码类代码

    2024-05-02 17:18:02
  • asp之家 网络编程 m.aspxhome.com