近期隨着隊列在項目中的使用愈來愈多,單個隊列的時間出來愈來愈長,單進程隊列處理,會致使後面的隊列被阻塞住,沒法及時響應處理,便會形成不良好的用戶體驗和功能誤差。php
目前在咱們使用的Laravel項目中,使用的廣播服務是redis,每次向客戶端廣播一次,都會生成一條Queue,假設每一個Queue的執行時間是1秒,假設用戶執行如下操做:mysql
//推送即時點贊提醒 1s dispatch(new NewLike($like)); //推送即時評論提醒 1s dispatch(new NewComment($comment)); //推送即時回覆提醒 1s dispatch(new NewReply($reply)); //推送即時通知提醒 1s dispatch(new NewNotite($notice)); //推送即時消息提醒 1s dispatch(new NewMessage($message));
以上每一個推送都將會耗時1秒以上,5個通知執行完成則須要5秒,假設系統天天產生10000次推送,則處理推送的時間10000 / 60 / 60 = 2.8(小時),則系統則須要花費2.8個小時才能將消息所有推送完成,可能會致使部分用戶沒法及時推送,從而對APP體驗產生反感。laravel
隨着系統推送愈來愈多,單進程隊列以及沒法知足咱們的需求,此時便須要開啓多個隊列消費者來進行處理。redis
開啓多個隊列消費者,就須要使用到多線程,每一個一個queue:work
都是一個單獨的進程,運行多個queue:work
進程就能夠達到同時處理多個任務的效果。sql
說了那麼多,上個代碼測試一下。多線程
經過artisan命令建立工具
art make:job TestJob
完善一下Job的主要邏輯:延遲1秒將傳入的ID寫入到日誌到中。測試
<?php namespace App\Jobs; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; class TestJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public $id; /** * Create a new job instance. * * @return void */ public function __construct($id) { $this->id = $id; } /** * Execute the job. * * @return void */ public function handle() { sleep(1); info($this->id); } }
我本地環境使用的job是基於mysql database,目前先填充10000個job進去。優化
for ($i = 0; $i < 10000; $i++) { dispatch(new TestJob($i)); } dd('done');
針對這10000個job,我本地運行了兩個queue:work
進程來進行同時處理。this
因爲本地運行測試,爲了方便,便把sleep移除了,下面來看看效果。
10000個job很快就被兩個queue:work
處理完成了。
運行完成後,最擔憂的問題莫過於,隊列任務是否會被另外一個消費者進行重複執行?
答案就是:不會,除非是其中一個任務處理超時(timeout)纔會有可能被其餘隊列進程重複執行到,關於爲何不會,下次將會經過寫一篇源碼解析來爲你們揭曉。
一般在服務端咱們使用的隊列進程管理工具一半都是Supervisor,知道上面須要開啓多個進程處理後,部分同窗便認爲只須要添加多個conf配置文件,就完成啦。
可是當咱們須要添加的隊列進程從2個變成8個、10個、20個、32個、64個。。。隨着須要處理的愈來愈多,豈不是須要添加n個配置文件來保持多進程隊列運行。
其實不是這樣的,Supervisor早就作到了這一點,能夠經過numprocs來控制進程數量進行處理,你能夠根據服務端負載狀況,來動態調整進程數量,配置以下:
[program:laravel-queue-work] process_name=%(program_name)s_%(process_num)02d directory=/data/yoursite command=php artisan queue:work autostart=true autorestart=true user=www numprocs=32 redirect_stderr=true
上面的案例中就開啓了32個進程進行同時處理了job。
以上就完成laravel項目多進程隊列的配置使用,同時從queue:work
輸出和日誌的寫入來看,多個進程同時運行,也並不會形成隊列重複執行的問題,能夠放心使用😁😁