如何使用 Laravel 隊列?下面由Laravel教程欄目給大家介紹一下使用 Laravel 隊列的方法,以及使用隊列的場景,希望對大家有所幫助!
為什么 ?
首先,我們要知道為什么要使用隊列,不使用隊列會怎么樣!優(yōu)缺點如何
我們可以舉例 幾個簡單場景。
郵件發(fā)送
郵件發(fā)送一般會面臨哪些問題 ??
- 發(fā)送緩慢
- 發(fā)送失敗
- 發(fā)送頻率過高,被服務商拒絕 又或者 被進入垃圾箱
使用隊列的好處在與哪里
-
提高客戶端響應
當發(fā)送時,我們不要立即處理,而是丟給服務器,且隊列進行管理和調度。 你可以自定義選擇立即發(fā)送 或者 根據(jù)配置延遲發(fā)送
-
提高容錯能力
在發(fā)送過程中,或許我們可能會遇到,目標被拒絕。例如大多數(shù)人 會遇到給
admin@qq.comn
發(fā)送報錯 502 的場景。 那這種場景,那么這種場景,我們可以理解其為是一個事件,在郵件發(fā)送的過程中,我們可以 引發(fā)構建出如下幾種事件- 發(fā)送失敗
- 郵件記錄入庫
- 代碼異常
- 郵件發(fā)送成功回調
- 發(fā)送失敗重試
通過此郵件發(fā)送,可能會導致多個耗時任務的產(chǎn)生,那我們其實也可以構建出多個 隊列服務 出來。每個隊列管理 自己的事情,很好的 解耦 他們
通過 Laravel 隊列 可以很好的進行設置 立即發(fā)送、延遲發(fā)送、重試發(fā)送
-
發(fā)送頻率可控
使用過批量發(fā)送的郵件的 開發(fā)者 必然會遇到一個問題,那便是,如果我們直接進行批量發(fā)送,即同一時間 進行大量的郵件發(fā)送。那么郵件服務商很可能會把我們的郵件給拒絕 或者 郵件進入垃圾箱,被識別為 廣告那么,這里便是用到了 延遲發(fā)送,我們可以根據(jù)當前隊列服務中,已知的 正在等待 投遞的郵件,合理的配置頻率,或者 切換郵件配置,來達到,頻率可控。
如設置 一個配置一分鐘之類發(fā)送10次,等等方案。 同樣,我們這里可以做到 配置、頻率控制、發(fā)送控制 解耦
其他
當然 我們還有很多種情況都會用到
- 服務器端下載 excel
- 服務器端異步多任務處理 大數(shù)據(jù)
- 錯誤消息處理
如何使用 Laravel 隊列
這里只是列出,大概的使用方向,和如何更好的去使用。代碼可能跑不起起來,主要是理解 邏輯 我們這里 使用的是 Redis 作為驅動
驅動設置為 Redis
> .env QUEUE_CONNECTION=redis > 在 config/queue.php 中可以找到
快速創(chuàng)建隊列 和 投遞任務
# 創(chuàng)建 任務 php artisan make:job ProcessPodcast
自動生成 app/Jobs/EmailJob.php
class EmailJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; protected $data; /** * Create a new job instance. * * @return void */ public function __construct(array $data) { $this->data = $data; } /** * Execute the job. * * @return void */ public function handle() { $service = new EmailService(); // ... 檢查當前可用 Mailer // 這里你自定義就好了,這個方法中你可以根據(jù)你自己的配置,獲取到當前可用的配置 $mailer = $service->getMailer(); // ... 獲取當前要發(fā)送的數(shù)據(jù) $data = $this->data; $service->send($mailer, $data); } }
一些常用操作
這些操作都能從 文檔中找到
調用 發(fā)送
# 延遲 2分鐘 發(fā)送 # 這里使用的是 Crontab 包 (不過 Laravel 自帶) EmailJob::dispatch()->delay(now()->addMinutes(2)); # 立即發(fā)送 (不會進入到隊列中) EmailJob::dispatchNow();
這里的隊列默認用的 是 defult 隊列,我們可以修改為指定隊列服務
public function __construct(array $data) { # 使用 emailQueue $this->onQueue('emailQueue'); $this->data = $data; }
設置失敗情況下重試次數(shù)
# 重試 5 次 public $tries = 5;
設置超時時間
/** * 確定任務應該超時的時間 * * @return DateTime */ public function retryUntil() { return now()->addMinutes(10); }
啟動我們的隊列
如果不配置 onQueue 的話,可以不帶 —queue 參數(shù)配置
php artisan queue:work --queue=emailQueue
結合 Events 來解耦
Laravel Event 也是通過 隊列實現(xiàn)的
# 創(chuàng)建 Event php artisan make:event FailEvent class FailEvent { use Dispatchable, InteractsWithSockets, SerializesModels; protected $data; protected $tag; /** * @param array $data 投遞的數(shù)據(jù) * @param string $tag 要操作的事情 */ public function __construct(array $data, string $tag = 'system') { $this->data = $data; $this->tag = $tag; } } # 創(chuàng)建 listener php artisan make:listener FailListener class FailListener { /** * Handle the event. * * @param object $event * @return void */ public function handle(FailEvent $event) { $this->{$event->tag}($event->data); } /** * 處理系統(tǒng)異常 * DateTime: 2021/12/3 11:02 上午 * @param array $data */ public function system(array $data) { } /** * 處理郵件異常 * DateTime: 2021/12/3 11:02 上午 */ public function email() { } } # app/Providers/EventServiceProvider.php protected $listen = [ FailEvent::class => [ FailListener::class, ], ] # 投遞 event(new FailEvent(['error' = '異常信息'], 'email'));
其他
其實,Laravel 大多數(shù)幫我實現(xiàn)了整個流程而已。可以嘗試自己使用 redis 來實現(xiàn)一個可控隊列。熟練是掌握 Redis 相關數(shù)據(jù)類型即可. 這里簡要列出 Redis 中,在以上模式中會用到的數(shù)據(jù)類型
-
List
使用 它可以完成 出棧 入棧的 隊列功能
-
Hash
使用他 可以用來存儲,序列化后的 Event 或者 Job __construct 傳入進去的數(shù)據(jù),盡量不要將整個 類 序列化進去
也可以實現(xiàn)存儲,Mailer 數(shù)據(jù)
-
Sorted Set
可以 設置時間為 Sorted Set 中的分數(shù),通過分數(shù)排序,找到我們最近要執(zhí)行的隊列任務
當然,Redis 的用法還有很多,滿足自己的需求即可。
世界上沒有完美的解決方案,只有最適合你自己的方案,在工作中遇到問題,盡量要學會舉一反三,合理的運用各種 工具,設計方案去實現(xiàn)。 代碼 只是最終一個縮影而已,最終的要學會理解,每個語言 每個框架,也只是一種方案的實現(xiàn),融會貫通才無敵 …