【Laravel】JobとQueueを使った非同期処理の作成方法と使い方

この記事からわかること

  • LaravelJob(ジョブ)やQueue(キュー)とは?
  • 使い方設定方法メリット

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

Laravelのデフォルトで備わっている機能の「ジョブ」と「キュー」。この機能を使うことで非同期で処理を実行させることができるようになります。今回はこれらの使い方やメリット、設定方法などをまとめていきたいと思います。

基礎知識

はじめに「ジョブ」と「キュー」がどのようなものか整理しておきます。

Job(ジョブ)とは?

Laravelでいう「Job(ジョブ)」とは処理そのもののこと。非同期で処理させたい内容を自分で定義し、そのひとまとまりになった処理自体をジョブと呼ぶ。

Queue(キュー)とは?

Queue(キュー)」とはジョブを非同期で実行するための仕組みのこと。イメージとしてはキューと呼ばれる箱の中にジョブをためていき、基本的には先入先出法(FIFO)で処理を実行していきます。

キュー(=ジョブの格納場所)はデータベースなどに用意します。「MySQL」といったリレーショナルデータベースや、NoSQLデータベースである「Redis」、AWSの「Amazon SQS」といったキューイングサービスなどと連携させることも可能です。

非同期処理のメリット

「ジョブ」と「キュー」を使うことで非同期処理を行うことができるようになります。非同期処理を行えることで時間のかかる処理を切り離すことができ、処理効率をグッと上げることができます。

例えば会員登録時にアップロードされた画像を編集する処理をジョブとして切り離すことで、データベース登録処理をスムーズに行うことが可能になります。

Laravelのジョブとキューを使ったメリットと非同期処理の仕組み

キューには次々とジョブが溜まっていき、任意のタイミングで実行され、消化されていきます。

まとめ

使い方と前準備

実際にジョブとキューを使って非同期処理を作成するためにはいくつかの前準備が必要です。今回はリレーショナルデータベース(MySQL)にジョブを登録する方法で実践してみます。

必要な前準備と手順

リレーショナルデータベースを使う際は「config/database.php」にデータベースの設定をすることを忘れないように注意してください。

.envファイルの修正

最初に設定を定義している隠しファイルの「.env」内のQUEUE_CONNECTION変数の部分を変更します。

QUEUE_CONNECTION=sync
          ↓
QUEUE_CONNECTION=database

デフォルトではsync(同期)で実行されるようになっているためこれをデータベースに変更しています。ここを変更していないとジョブはデータベースにたまらず、普通に実行されてしまうので注意してください。

キュードライバも明示的に指定しておくため以下のコードを「.env」に追記しておきます。

QUEUE_DRIVER=database

DBにキューテーブルを作成する

キューテーブルを作成するためのマイグレーションファイルはartisanコマンドで自動作成できます。作成したらマイグレーションを実行します。

$ php artisan queue:table
Migration created successfully.

$ php artisan migrate
Migrating: 2022_06_07_104702_create_jobs_table
Migrated:  2022_06_07_104702_create_jobs_table (60.91ms)

これでdatabase/migrationsディレクトリ内に20XX_XX_XX_XXXXXXX_create_jobs_table.phpが作成され、紐づけているデータベースにも「jobsテーブル」が生成されています。

マイグレーションファイル(一部)

public function up()
{
    Schema::create('jobs', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('queue')->index();
        $table->longText('payload');
        $table->unsignedTinyInteger('attempts');
        $table->unsignedInteger('reserved_at')->nullable();
        $table->unsignedInteger('available_at');
        $table->unsignedInteger('created_at');
    });
}

ジョブクラスの作成

ジョブクラスはapp/jobs内に格納します。専用のmakeコマンドが用意されているので実行すると自動でjobsディレクトリと該当ファイルが生成されます。

$ php artisan make:job TestJobs
Job created successfully.

app/jobs/TestJobs

<?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;

// 例としてエロクアントを用いる
use App\Models\User;

class TestJobs 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()
    {
        // ここに処理を記述する

        // 例:エロクアントを用いたDBへのインサート処理
        $user = new User;
        $user->name = "jobs";
        $tech->save();
    }
}

ジョブクラスの中にはhandleメソッドが用意されます。キューからジョブが呼び出された時に実行させたい処理をここに記述します。

上記は例としてエロクアントを用いたDBへのインサート処理を記述しています。

あとはジョブを溜めたい箇所でdispatchメソッドを呼び出すだけです。その際はuse文で読み込むのを忘れないようにしてください。今回はアクセスされた時にジョブを溜めるような仕組みを作ってみます。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
// 追記
use App\jobs\TestJobs;

class appController extends Controller
{
    public function index(Request $request)
    {
        // ジョブを溜める
        TestJobs::dispatch();
        return view('index');
    }
}

ルーティングでこのコントローラーのindexアクションメソッドを実行するように設定すれば、アクセスされたタイミングでデータベースにジョブが溜まります。溜まったジョブはこのままでは実行されないのでコマンドを叩いて実行させます。

キューに溜まったジョブを実行する(Worker)

キューに溜まったジョブはWorkerを使って実行させます。Workerは以下のコマンドで起動し、ジョブを実行してくれます。

$ php artisan queue:work

[2022-06-07 11:24:58][1] Processing: App\Jobs\TestJobs
[2022-06-07 11:24:58][1] Processed:  App\Jobs\TestJobs

正常に終了するとデータベース内に溜まっていたジョブは自動で消去されます。

Workerの起動時のオプション

Workerの起動時にオプションを渡すことも可能です。

キューから1個のジョブのみ実行

$ php artisan queue:work --once

キューから100個のジョブを実行

$ php artisan queue:work --max-jobs=100

キューにある全てのジョブを実行

$ php artisan queue:work --stop-when-empty

キューにあるジョブを1時間の間だけ実行

$ php artisan queue:work --max-time=3600

キューにあるジョブの優先度が高いものから実行

$ php artisan queue:work --queue=high,low

キューの名前を指定して実行

$ php artisan queue:work --queue=キューの名前

キューの名前はdispatchメソッドのonQueueメソッドで指定できます。

 TestJobs::dispatch()->onQueue('foo');

条件付きでディスパッチさせる

 TestJobs::dispatchIf($judge);

ジョブを溜めずに同期処理としてディスパッチ

 TestJobs::dispatchSync();

ジョブに引数を渡す

 TestJobs::dispatch($foo);

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index