Laravel 寫個 Queue 怎麼這麼難

這兩天初次接觸 Laravel 的隊列,也是搞了好一會。。。一番折騰下來仍是感慨對 Laravel 不得其門,文檔寫的相對簡單和歸納,看源碼又有些力不從心(不過看源碼慢慢調試驗證仍是最可靠的)。php

下面是個人一個簡單 Demo,僅僅使用了隊列的最基本操做,偏高級的操做須要再去好好時間一番 :)laravel

和我同樣入門 Laravel 的隊列有些困難的同窗能夠交流一下。redis

配置

添加 Redis 包

composer.jsonrequire 部分加入 "predis/predis": "~1.0",,而後 composer up 更新一下便可。數據庫

database.php

database.php 配置文件中對 redis 數據庫部分進行配置,默認有一個 default 鏈接,就用這個好了:)json

根據這個默認鏈接中須要的配置項,編輯 .env 配置文件,將其中的 REDIS_HOSTREDIS_PASSWORDREDIS_PORT 填寫成本身服務器中 Redis 的相應值。服務器

queue.php

首先須要去 .env 中配置 QUEUE_DRIVER,由於如今打算用 Redis,因此配置成 redisapp

接着配置 queue.php 裏 connections 部分的 redis 鏈接,其中 connection 對應的值就是 database.php 中 redis 的那個 default 鏈接。composer

任務類

接下來就是寫實際的操做類了,Laravel 提供了 artisan 命令簡化建立任務類:框架

php artisan make:job Demo

app 目錄下會生成 Jobs 目錄,裏面已經有了 Demo.php 任務類。函數

Lumen 可沒有這個 artisan 命令,不過也很方便,默認會有一個 ExampleJob.php 已經寫好了,拷貝一份改個名字便可。

先寫個簡單的日誌輸出測試一下好了,在 handle 方法中:

Log::info('Hello, queue');

發聽任務

如今寫個入口函數,推送任務到隊列中。使用輔助函數 dispatch()

Laravel 中使用以下方式:

Demo::dispatch();

Lumen 中使用以下方式:

dispatch(new Demo);

開啓隊列

順利的話,這是最後一步了。命令行中執行:

php artisan queue:listen --queue=default

它會監聽隊列,並輸出簡單的執行狀況,好比:

[2017-11-07 02:12:47] Processing: App\Jobs\Demo
[2017-11-07 02:12:47] Processed:  App\Jobs\Demo

沒啥問題後就可讓這個隊列腳本執行在後臺:

php artisan queue:work --daemon --quiet --queue=default 1>> /dev/null 2>&1 &

進階一下 :)

推送到隊列中時,通常會有傳參的需求,那這裏怎麼傳呢?

參數傳遞

傳入

在入口函數中傳入參數方式以下:

Laravel 中使用以下方式:

$param = 'Stephen';
Demo::dispatch($param);

Lumen 中使用以下方式:

$param = 'Stephen';
dispatch(new Demo($param));

接收

在任務類中接收參數方式以下:

protected $param;

/**
 * Create a new job instance.
 *
 * @return void
 */
public function __construct($param)
{
    $this->param = $param;
}

/**
 * Execute the job.
 *
 * @return void
 */
public function handle()
{
    Log::info('Hello, ' . $this->param);
}

初次嘗試到此爲止,還有許多高級用法,好比延遲分發、錯誤處理、優先級、失敗處理等,後續會繼續寫 :)

多隊列

這是一個必然須要考慮到的問題,我不可能將全部任務都放在一個叫 default 的隊列中,這樣不容易對隊列進行管理。

要指定不一樣的隊列,很是簡單,在 dispatch() 後緊接着跟上 onQueue() 方法便可:

Demo::dispatch()->onQueue('emails');

不對啊,我好像沒有定義過這個叫 emails 的 queue。嗯,天然須要作出一點改動,在 queue.php 配置文件中的 redis 配置 queuedefault 改成 {default},這樣作的效果就是隊列的名稱能夠從運行的時候動態拿到,而不是寫死的。

若是使用 Lumen 框架,那麼直接這麼寫會報錯:Call to a member function onQueue() on string

緣由在於 Lumen 的 Job 基類中並無使用 Illuminate\Foundation\Bus\Dispatchable 這個 trait,而是直接使用 Illuminate\Bus\Queueable 中的 onQueue() 方法。

那麼如今就很清楚了,咱們的 Job 類使用了 Illuminate\Bus\Queueable 這個 trait,因此須要在 Job 類上調用這個 onQueue() 方法。

$job = new XXXJob();
dispatch($job->onQueue('queue-name'));

當咱們在開啓隊列的時候:

php artisan queue:work --queue=emails

這裏指定的隊列名 emails 和 dispatch 時指定的隊列名保持一致便可。

參考連接

相關文章
相關標籤/搜索