昨天我們提到了怎麼利用快取,來讓我們的服務提高效率。
不過有些時候,即使用上了快取,用戶的體驗還是沒有辦法提升到令人滿意的程度。
這些時候,我們可以考慮將一些比較費時的任務,轉換到排程(Queue)內處理。
今天,我們來看看在 Laravel 內怎麼實作這件事情!
首先,我們先看 queue 的設置,在 Laravel 內,放在 config/queue.php
內
'default' => env('QUEUE_CONNECTION', 'sync'),
這邊要注意, sync
這個驅動並不會實際的將任務分配進 queue,而是會等任務做完了之後再往下進行。
如果是實際上線的產品,或者你想要練習開發中實際運作 queue,建議可以用 redis
來操作
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'block_for' => null,
'after_commit' => false,
],
這邊建議可以在 .env
內設置 REDIS_QUEUE
。
設置沒有問題之後,我們可以開始建立任務。
這邊相信讀者(略
./vendor/bin/sail artisan make:job ProcessPodcast
INFO Job created successfully.
就會建立在 app/Jobs/ProcessPodcast.php
裡面
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ProcessPodcast implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
//
}
}
這邊就可以撰寫你想要的邏輯了
比方說,既然是 ProcessPodcast
,你可能會想要注入 Podcast
use App\Models\Podcast;
public function __construct(Podcast $podcast)
{ }
管理好了之後,可以使用 dispatch
來發布 Job
class PodcastController extends Controller
{
public function store(Request $request)
{
$podcast = Podcast::create(/* ... */);
ProcessPodcast::dispatch($podcast);
}
}
如果你選用了不會立刻執行的設置,但是某些狀況下,希望能立刻執行該任務,可以用 dispatchSync()
ProcessPodcast::dispatchSync($podcast);
如果你希望任務發布後,要等一段時間才有機會被執行,可以用 delay()
ProcessPodcast::dispatch($podcast)
->delay(now()->addMinutes(10));
任務發布的部分,大概就介紹這幾種做法。
發布任務到 queue 裡面後,下一步就是找人去執行這些任務了。
這邊我們可以簡單地透過指令呼叫 queue worker
./vendor/bin/sail artisan queue:work
呼叫之後, worker 就會起來,開始運作該執行的任務了。
這邊要注意,即使任務全部執行完畢, queue worker 也不會終止,而是會持續的等 queue 出現新任務。
今天有關 queue 的基礎,就先介紹到這邊。其實 queue 還有很多可以介紹的細節,比方說怎麼定義一個任務失敗,讓失敗的任務可以放在失敗任務的表內。
以及,怎麼規劃 worker 在某個時間點,重新處理這些失敗的任務。是將這些任務清除掉呢,還是重新執行?
有關 queue worker,也可以討論這個程式是不是會意外中斷,為了避免意外中斷,我們可以用 supervisor
監督該 worker
apt-get install supervisor
不過,這些議題都比較進階了!所以我們就以後再說吧!各位明天見!