前言
laravel中的隊列服務(wù)跟其他隊列服務(wù)也沒有什么不同,都是最符合人類思維的最簡單最普遍的流程:有一個地方存放隊列信息,一個PHP進(jìn)程在運行時將任務(wù)寫入,另外一個PHP守護(hù)進(jìn)程輪詢隊列信息,將達(dá)到執(zhí)行要求的任務(wù)執(zhí)行并刪除。由于PHP是url驅(qū)動的同步語言,本身是阻塞的,所以laravel提供一個守護(hù)進(jìn)程工具來查詢并執(zhí)行隊列信息也就不足為奇了。
這兩天初次接觸 Laravel 的隊列,也是搞了好一會。。。一番折騰下來還是感慨對 Laravel 不得其門,文檔寫的相對簡單和概括,看源碼又有些力不從心(不過看源碼慢慢調(diào)試驗證還是最可靠的)。
下面是我的一個簡單 Demo,僅僅使用了隊列的最基本操作,偏高級的操作需要再去好好時間一番 :)
和我一樣入門 Laravel 的隊列有些困難的同學(xué)可以交流一下。
配置
添加 Redis 包
在 composer.json 中 require 部分加入 "predis/predis": "~1.0",,然后 composer up 更新一下即可。
database.php
在 database.php 配置文件中對 redis 數(shù)據(jù)庫部分進(jìn)行配置,默認(rèn)有一個 default 連接,就用這個好了:)
根據(jù)這個默認(rèn)連接中需要的配置項,編輯 .env 配置文件,將其中的 REDIS_HOST、REDIS_PASSWORD、REDIS_PORT 填寫成自己服務(wù)器中 Redis 的相應(yīng)值。
queue.php
首先需要去 .env 中配置 QUEUE_DRIVER,因為現(xiàn)在打算用 Redis,所以配置成 redis。
接著配置 queue.php 里 connections 部分的 redis 連接,其中 connection 對應(yīng)的值就是 database.php 中 redis 的那個 default 連接。
任務(wù)類
接下來就是寫實際的操作類了,Laravel 提供了 artisan 命令簡化創(chuàng)建任務(wù)類:
php artisan make:job Demo
在 app 目錄下會生成 Jobs 目錄,里面已經(jīng)有了 Demo.php 任務(wù)類。
Lumen 可沒有這個 artisan 命令,不過也很方便,默認(rèn)會有一個 ExampleJob.php 已經(jīng)寫好了,拷貝一份改個名字即可。
先寫個簡單的日志輸出測試一下好了,在 handle 方法中:
Log::info('Hello, queue');
發(fā)放任務(wù)
現(xiàn)在寫個入口函數(shù),推送任務(wù)到隊列中。使用輔助函數(shù) dispatch():
Laravel 中使用如下方式:
Lumen 中使用如下方式:
開啟隊列
順利的話,這是最后一步了。命令行中執(zhí)行:
php artisan queue:listen --queue=default
它會監(jiān)聽隊列,并輸出簡單的執(zhí)行情況,比如:
[2017-11-07 02:12:47] Processing: App\Jobs\Demo
[2017-11-07 02:12:47] Processed: App\Jobs\Demo
沒啥問題后就可以讓這個隊列腳本執(zhí)行在后臺:
php artisan queue:work --daemon --quiet --queue=default 1>> /dev/null 2>1
進(jìn)階一下 :)
推送到隊列中時,一般會有傳參的需求,那這里怎么傳呢?
參數(shù)傳遞
傳入
在入口函數(shù)中傳入?yún)?shù)方式如下:
Laravel 中使用如下方式:
$param = 'Stephen';
Demo::dispatch($param);
Lumen 中使用如下方式:
$param = 'Stephen';
dispatch(new Demo($param));
接收
在任務(wù)類中接收參數(shù)方式如下:
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);
}
初次嘗試到此為止,還有許多高級用法,比如延遲分發(fā)、錯誤處理、優(yōu)先級、失敗處理等,后續(xù)會繼續(xù)寫 :)
多隊列
這是一個必然需要考慮到的問題,我不可能將所有任務(wù)都放在一個叫 default 的隊列中,這樣不容易對隊列進(jìn)行管理。
要指定不同的隊列,非常簡單,在 dispatch() 后緊接著跟上 onQueue() 方法即可:
Demo::dispatch()->onQueue('emails');
不對啊,我好像沒有定義過這個叫 emails 的 queue。嗯,自然需要做出一點改動,在 queue.php 配置文件中的 redis 配置 queue 從 default 改為 {default},這樣做的效果就是隊列的名稱可以從運行的時候動態(tài)拿到,而不是寫死的。
如果使用 Lumen 框架,那么直接這么寫會報錯:Call to a member function onQueue() on string。
原因在于 Lumen 的 Job 基類中并沒有使用 Illuminate\Foundation\Bus\Dispatchable 這個 trait,而是直接使用 Illuminate\Bus\Queueable 中的 onQueue() 方法。
那么現(xiàn)在就很清楚了,我們的 Job 類使用了 Illuminate\Bus\Queueable 這個 trait,所以需要在 Job 類上調(diào)用這個 onQueue() 方法。
$job = new XXXJob();
dispatch($job->onQueue('queue-name'));
當(dāng)我們在開啟隊列的時候:
php artisan queue:work --queue=emails
這里指定的隊列名 emails 和 dispatch 時指定的隊列名保持一致即可。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
參考鏈接
Laravel 官方文檔
您可能感興趣的文章:- PHP的Laravel框架中使用消息隊列queue及異步隊列的方法
- Laravel 4.2 中隊列服務(wù)(queue)使用感受