这里有新鲜出炉的Laravel 5.0官方中文教程,程序狗速度看过来!
Laravel是一套简洁、优雅的PHP Web开发框架(PHP Web Framework)。它可以让你从面条一样杂乱的代码中解脱出来;它可以帮你构建一个完美的网络APP,而且每行代码都可以简洁、富于表达力。
本篇文章主要介绍了浅谈Laravel队列实现原理解决问题记录,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
问题
公司项目使用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结构实现的,
是将value推入键值为key的redis队列,key的值则是通过
- rpush(key, value)
获取到的
- $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 是添加队列时
- 'queue' => 'default'
传入的。
- $this->dispatch( new jobClass()->onQueue($queue) )
- // config\queue.php 文件中的redis配置部分
- 'redis' => [
- 'driver' => 'redis',
- 'connection' => 'default',
- 'queue' => 'default',
- 'expire' => 60,
- ],
至此,两个项目的队列冲突原因就找到了。因为redis队列配置中
都使用的默认的default,所以当共用redis时,默认的队列list 都是'queue:default',所以导致了冲突。
- '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
最后
遇到问题,莫要病急乱投医。从代码入手,分析理解实现原理,找对点,解决方法也许很简单,希望对大家的学习有所帮助,也希望大家多多支持PHPERZ。
来源: http://www.phperz.com/article/17/1026/350582.html