首頁  >  文章  >  後端開發  >  關於Laravel隊列的實作原理以及如何解決問題

關於Laravel隊列的實作原理以及如何解決問題

不言
不言原創
2018-06-13 11:45:522358瀏覽

本篇主要介紹了淺談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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn