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