本篇主要介紹了淺談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結構實現的,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
##最後
#遇到問題,莫要病急亂投醫。從程式碼入手,分析理解實作原理,找對點,解決方法也許很簡單。 以上就是本文的全部內容,希望對大家的學習有所幫助,更多相關內容請關注PHP中文網! 相關推薦:關於PHP的Laravel框架中使用訊息佇列queue及非同步佇列的方法分析
以上是關於Laravel隊列的實作原理以及如何解決問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!