1 環(huán)境
Laravel是一種類似ThinkPHP的php框架,封裝的諸多功能可以很方便的使用。隊(duì)列Queue便是其中之一。
Windows環(huán)境下,可使用PHPstorm作為Laravel的集成開發(fā)環(huán)境IDE。
2 隊(duì)列
Laravel可配置多種隊(duì)列驅(qū)動,包括 "sync", "database", "beanstalkd", "sqs", "redis", "null"(具體參見app/config/queue.php)
其中sync為同步,database為使用數(shù)據(jù)庫,后面三種為第三方隊(duì)列服務(wù),最后一種為不使用隊(duì)列。
通過在 .env 中的 QUEUE_CONNECTION 選項(xiàng),來決定選擇何種驅(qū)動。
如 QUEUE_CONNECTION=database 即為選擇數(shù)據(jù)庫驅(qū)動隊(duì)列。
3 原理
所謂隊(duì)列,會有數(shù)據(jù)的生產(chǎn)者和消費(fèi)者之分。生產(chǎn)者向隊(duì)列中投遞數(shù)據(jù),消費(fèi)者從隊(duì)列中獲取數(shù)據(jù)。
比如向用戶發(fā)送郵件的場景:現(xiàn)在有10w封郵件需要發(fā)送,最簡單的,我們需要有一個(gè)方法將郵件的收件人、內(nèi)容等,拆分成10w條任務(wù)放在隊(duì)列中,同時(shí)需要設(shè)置一個(gè)回調(diào)方法負(fù)責(zé)處理每條任務(wù)。當(dāng)隊(duì)列中有郵件發(fā)送任務(wù)時(shí),隊(duì)列會主動調(diào)用回調(diào)方法,并傳遞任務(wù)詳情進(jìn)去?;卣{(diào)方法處理完成后,單條郵件即發(fā)送完畢。其他郵件依樣處理。
4 使用數(shù)據(jù)庫驅(qū)動隊(duì)列
4.1 生成任務(wù)表
在終端下輸入
php artisan queue:table
php artisan migrate
在數(shù)據(jù)庫連接正常的情況下,會在數(shù)據(jù)庫中出現(xiàn)jobs表:
[id] bigint
[queue] nvarchar(255)
[payload] nvarchar(max)
[attempts] tinyint
[reserved_at] int
[available_at] int
[created_at] int
4.2 創(chuàng)建任務(wù)類
php artisan make:job SendEmail
在終端內(nèi)執(zhí)行上述命令,會自動生成 app/Jobs/SendMail.php 文件
class SendMail implements ShouldQueue
在該文件的handle方法中,可以放置任務(wù)處理邏輯。
4.3 發(fā)送任務(wù)
在任意位置,均可像下面一樣調(diào)用 dispatch 發(fā)送任務(wù)
SendMail::dispatch($email);
4.4 驅(qū)動隊(duì)列
完成上述步驟后,可以在數(shù)據(jù)庫中發(fā)現(xiàn)一條記錄(導(dǎo)出為insert SQL語句):
復(fù)制代碼 代碼如下:
INSERT INTO [jobs]([id], [queue], [payload], [attempts], [reserved_at], [available_at], [created_at]) VALUES (6, N'default', N'{"displayName":"App\\Jobs\\ProcessPodcast","job":"Illuminate\\Queue\\CallQueuedHandler@call","maxTries":null,"timeout":null,"timeoutAt":null,"data":{"commandName":"App\\Jobs\\ProcessPodcast","command":"O:23:\"App\\Jobs\\ProcessPodcast\":8:{s:29:\"\u0000App\\Jobs\\ProcessPodcast\u0000data\";s:6:\"111222\";s:6:\"\u0000*\u0000job\";N;s:10:\"connection\";N;s:5:\"queue\";N;s:15:\"chainConnection\";N;s:10:\"chainQueue\";N;s:5:\"delay\";N;s:7:\"chained\";a:0:{}}"}}', 0, NULL, 1545980176, 1545980176);
此時(shí)任務(wù)已經(jīng)放置在數(shù)據(jù)庫內(nèi),只有將隊(duì)列運(yùn)行起來后,隊(duì)列才能主動調(diào)用回調(diào)方法。
在終端內(nèi)運(yùn)行上述命令即可。該命令還有諸多參數(shù),如deamon、tries等,可根據(jù)需要指定。
4.5 守護(hù)進(jìn)程
為了保證應(yīng)用服務(wù)的穩(wěn)定性,需要開啟守護(hù)進(jìn)程。
Linux下,一般使用 Supervisor ,Windows下使用 Forever
4.6 執(zhí)行失敗的處理
對于處理失敗的任務(wù),Laravel也提供的解決方案。通過運(yùn)行如下命令,即可創(chuàng)建表以記錄失敗任務(wù)。
php artisan queue:failed-table
php artisan migrate
在數(shù)據(jù)庫中即生成 failed_jobs :
[id] bigint
[connection] nvarchar(max)
[queue] nvarchar(max)
[payload] nvarchar(max)
[exception] nvarchar(max)
[failed_at] datetime
導(dǎo)致任務(wù)失敗的 Exception 會被傳遞到 SendMail 的 failed 方法,因而你需要在SendMail中自行實(shí)現(xiàn)該方法,并做進(jìn)一步處理。
任務(wù)執(zhí)行失敗的原因有很多,如傳參錯(cuò)誤、嘗試次數(shù)超過限制、超時(shí)、甚至在 handle 方法中拋出異常,均會作為失敗任務(wù)處理。
4.7 任務(wù)執(zhí)行前后的處理
Laravel提供了任務(wù)執(zhí)行前后的處理入口,即在 App/Providers/AppServiceProvider 中的 boot() 中加入如下代碼:
public function boot()
{
Queue::before( function (JobProcessing $event) {
Log::info("處理任務(wù)前");
});
Queue::after( function (JobProcessed $event) {
Log::info("處理任務(wù)后");
});
}
傳遞的 $event 中,帶有任務(wù)詳情,幾個(gè)簡單的例子:
$event->connectionName
$event->job
$event->job->payload()
5 使用 Redis 驅(qū)動隊(duì)列
5.1 Laravel 安裝 Predis 包
在 Laravel 中使用 Redis 之前,需要通過 Composer 安裝 predis/predis 包:
composer require predis/predis
上述拓展是幫助Laravel與Redis打交道的,我們現(xiàn)在還缺少Redis服務(wù)。
如果此時(shí)將 .env 中的 QUEUE_CONNECTION 改為 redis,訪問時(shí)會報(bào)錯(cuò):
Predis \ Connection \ ConnectionException (10061)
����Ŀ����������ܾ��������ӡ� [tcp://127.0.0.1:6379]
5.2 配置 Redis 服務(wù)
在Redis官網(wǎng) 下載源碼后自行編譯即可。
官方并未提供Windows版,Redis的Windows版式由微軟工作組維護(hù)的,你可以從其GitHub頁 找到。不過貌似已經(jīng)不再維護(hù)了,最新的版本是16年發(fā)布的3.2.100。
Linux下通過簡單的運(yùn)行
即可開啟服務(wù),再通過
來嘗試使用Redis。使用也很簡單,就是 set key value 和 get key。
Windows下安裝后,在命令行中 cd 到安裝目錄
C:\Program Files\Redis>redis-server redis.windows.conf
C:\Program Files\Redis>netstat -an|find "6379"
TCP 127.0.0.1:6379 0.0.0.0:0 LISTENING
即可開啟Redis服務(wù)。
Redis服務(wù)的停止是通過如下命令:
C:\Program Files\Redis>redis-server --service-stop
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
您可能感興趣的文章:- laravel5.6 框架郵件隊(duì)列database驅(qū)動簡單demo示例
- Laravel使用Queue隊(duì)列的技巧匯總
- Docker部署Laravel應(yīng)用實(shí)現(xiàn)隊(duì)列&任務(wù)調(diào)度
- Laravel 6 將新增為指定隊(duì)列任務(wù)設(shè)置中間件的功能
- Laravel框架隊(duì)列原理與用法分析
- Laravel中為什么不使用blpop取隊(duì)列詳析
- 關(guān)于 Laravel Redis 多個(gè)進(jìn)程同時(shí)取隊(duì)列問題詳解
- 源碼分析 Laravel 重復(fù)執(zhí)行同一個(gè)隊(duì)列任務(wù)的原因
- Laravel使用消息隊(duì)列需要注意的一些問題
- Laravel中利用隊(duì)列發(fā)送郵件的方法示例
- 淺談Laravel隊(duì)列實(shí)現(xiàn)原理解決問題記錄
- 淺析Laravel5中隊(duì)列的配置及使用
- PHP的Laravel框架中使用消息隊(duì)列queue及異步隊(duì)列的方法
- Laravel 4.2 中隊(duì)列服務(wù)(queue)使用感受
- Laravel框架中隊(duì)列和工作(Queues、Jobs)操作實(shí)例詳解