前言
Laravel的隊(duì)列可以用在輕量級(jí)的隊(duì)列需求中沟优。比如我們系統(tǒng)中的短信、郵件等功能病苗,這些功能有一些普遍的特征疗垛,異步、重試硫朦、并發(fā)控制等贷腕。Laravel現(xiàn)在主要支持的隊(duì)列服務(wù)有Null、Sync咬展、Database泽裳、Redis、Beanstalkd破婆、Sqs涮总。
在我們的項(xiàng)目中(消息中心、人事)用的主要是redis祷舀,接下來(lái)我會(huì)介紹下隊(duì)列基于redis驅(qū)動(dòng)的運(yùn)行機(jī)制瀑梗。
背景知識(shí)
Laravel啟動(dòng)后,加載config/app.php的providers數(shù)組中的服務(wù)提供者 QueueServiceProvider裳扯,在隊(duì)列服務(wù)提供者中抛丽,已經(jīng)注冊(cè)了一系列相關(guān)服務(wù)。
在.env配置文件中嚎朽,我們?cè)O(shè)置了QUEUE_DRIVER為redis铺纽,系統(tǒng)啟動(dòng)后會(huì)自動(dòng)生成Redis連接,同時(shí)注冊(cè)了Work消費(fèi)者哟忍,隊(duì)列監(jiān)聽(tīng)器以及錯(cuò)誤服務(wù)。在queue.php和database.php配置中都默認(rèn)了相關(guān)的redis設(shè)置陷寝。
任務(wù)調(diào)度
調(diào)度如下:
laravel 的隊(duì)列服務(wù)由兩個(gè)進(jìn)程控制锅很,一個(gè)是事件生產(chǎn)者(黑線),一個(gè)是事件消費(fèi)者(黃線)凤跑。
有三個(gè)隊(duì)列爆安,主隊(duì)列 queues:default(下面default代替),延時(shí)隊(duì)列 queues:default:delayed(下面delayed代替)仔引,待處理隊(duì)列 queues:default:reserved(下面reserved代替)扔仓。所有的隊(duì)列事件都由事件消費(fèi)者去消費(fèi)主隊(duì)列中的事件褐奥。(隊(duì)列名稱default在queue.php中被定義)
1. 事件觸發(fā):dispatch(new Event());
事件觸發(fā)后翘簇,dispatch判斷Event是否繼承隊(duì)列類撬码,是,將事件分發(fā)到隊(duì)列執(zhí)行流程中版保。隊(duì)列執(zhí)行流程會(huì)根據(jù)Event的延時(shí)屬性判斷呜笑,否,將Event放到即時(shí)處理queues:default 隊(duì)列中彻犁,是叫胁,將Event放入延時(shí) queues:default:delayed 隊(duì)列中。
2. 消費(fèi):php artisan queue:work
圖中A汞幢、B驼鹅、C、D為消費(fèi)者進(jìn)程依次執(zhí)行步驟森篷,淡黃色背景的代碼備注都為對(duì)隊(duì)列的操作命令(predis 實(shí)現(xiàn)redis api)输钩,每個(gè)備注里面對(duì)事件的操作要么一起成功,要么一起失敿埠辍(Lua腳本)张足。
3. A: 對(duì)delayed、default隊(duì)列操作
A1:取出小于當(dāng)前時(shí)間的(時(shí)間戳)所有Event坎藐,賦給val为牍,刪除delayed隊(duì)列中0到val.length長(zhǎng)度的Event(redis的有序集合有一個(gè)分?jǐn)?shù),有序集合根據(jù)這個(gè)分?jǐn)?shù)從小到大排序岩馍,這里的時(shí)間戳就是分?jǐn)?shù))碉咆。
A2:將上面獲取的Event,放入到主隊(duì)列 default蛀恩。
4. B: 對(duì)reserved疫铜、default隊(duì)列操作
B1:取出小于當(dāng)前時(shí)間的所有Event,賦給val双谆,刪除reserved隊(duì)列中0到val長(zhǎng)度的Event壳咕。
B2:將上面獲取的Event,放入到主隊(duì)列 default顽馋。
5. C: 對(duì)default谓厘、reserved隊(duì)列操作
C1:取出主隊(duì)列中的所有Event。
C2:將Event放入reserved寸谜,且記錄Event的執(zhí)行次數(shù)(保留Event竟稳,由D執(zhí)行后,根據(jù)Event執(zhí)行結(jié)果處理這些Event)。
6. D: 處理Event(由C步驟得到的Event他爸,交給D)
根據(jù)得到的Event依次執(zhí)行(也就是通知監(jiān)聽(tīng)這個(gè)Event的所有監(jiān)聽(tīng)者)聂宾,同時(shí)刪除reserved隊(duì)列的相對(duì)應(yīng)的Event(無(wú)論執(zhí)行失敗還是成功),如果執(zhí)行失敗會(huì)將任務(wù)放入reserved隊(duì)列中诊笤,執(zhí)行時(shí)間為1540097000(1540096910 + 90系谐,90為設(shè)置的延時(shí)時(shí)間),以便下次執(zhí)行盏混。
結(jié)尾
以上就是Laravel隊(duì)列所有的執(zhí)行流程蔚鸥,當(dāng)然里面包括執(zhí)行失敗的錯(cuò)誤處理、如何通知監(jiān)聽(tīng)者等細(xì)節(jié)都沒(méi)講许赃,大家可以自行分析代碼理解止喷。