LoginSignup
23

More than 5 years have passed since last update.

Laravel5.7で非同期処理がしたい

Last updated at Posted at 2018-12-10

この記事はニフティグループ Advent Calendar 2018の11日目の記事です。

以降では、Laravel(5.7)で非同期処理を実装してHorizonで動かしてみる、ということをしてみます。
(Laravelが動く環境はすでにあることを想定しています。Laradocなどで作成しておいてください。)

目次

  1. Laravel(5.7)で非同期処理を実装する
    1. 非同期に実行したい処理を実装する
    2. コントローラーから呼び出す
    3. 試しに同期的に実行してみる
  2. Redisキューを使って動かしてみる
  3. Laravel Horizonで動かしてみる
  4. さいごに

1. Laravel(5.7)で非同期処理を実装する

LaravelにはQueueサービスというものがあり、Beanstalkd、Amazon SQS、Redisなどをキューとして用いた非同期処理が簡単に実装できます。

詳しくは公式のドキュメントを御覧ください。

1.1 非同期に実行したい処理を実装する

以下のコマンドを実行すると、app/Jobs配下にProcessSampleというクラスが生成されます。このクラスに非同期処理(ジョブ)を実装していきます。

php artisan make:job ProcessSample

作成したクラスの handle メソッドが、実際にジョブが実行されるときに呼び出される関数です。
試しに、適当なテキストを受け取って、実行時にログを出力するジョブを作ってみました。

app/Jobs/ProcessSample.php
<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class ProcessSample implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    private $text;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($text)
    {
        $this->text = $text;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        logger()->info("It's work! | ".$this->text);
    }
}

1.2 コントローラーから呼び出す

dispatch という関数でジョブをキューに追加します。
引数は ProcessSample のコンストラクタに渡されます。

routes/web.php
use App\Jobs\ProcessSample;

Route::get('/test/{text}', function ($text) {
    ProcessSample::dispatch($text);
    return 'Queued!';
});

1.3 試しに同期的に実行してみる

.envファイルのQUEUE_CONNECTIONが実際にどのキューを使うかの設定です。
Amazon SQSやRedisなどを指定することができます。

ここではまず動くか確かめたいので、同期的に実行するようsyncと設定します。

.env
QUEUE_CONNECTION=sync

さきほど/test/{text}というURLを設定したので/test/sampletextにアクセスしてみます。

storage/logs/laravel-2018-12-11.log
[2018-12-11 **:**:**] local.INFO: It's work! | sampletext

このようなログが出力されていたら成功です🎉

2. Redisキューを使って動かしてみる

Redisを準備する

Redis本体は各自ご用意ください。
LaradocであればRedisは含まれているので以下で起動できます。

docker-compose up -d redis

パッケージの追加と設定

LaravelでRedisをキューとして使うにはPredisが必要なので、プロジェクトに追加します。

composer require predis/predis

Redisをキューとして使うように設定します。

.env
QUEUE_CONNECTION=redis

# 以下は環境に合わせて設定してください
REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379

Redisの設定は以上です!

動かしてみる

次は実際にキューを監視させます。

php artisan queue:work

この状態で/test/sampletext2にアクセスしてみます。

storage/logs/laravel-2018-12-11.log
[2018-12-11 **:**:**] local.INFO: It's work! | sampletext2

このようなログが出力されていたら成功です🎉
非同期処理の実装、完璧です✨

3. Laravel Horizonで動かしてみる

HorizonはLaravelのRedisキューの監視ツールです。
非同期処理をする分には上記までの手順で問題ないのですが、Horizonにはダッシュボードがあり、処理のスループットや失敗などを確認することができて楽しいので使ってみます。

詳しくは公式のドキュメントを御覧ください。

Screen Shot 2018-12-11 at 2.41.33.png

パッケージの追加

Horizonをプロジェクトに追加します。

composer require laravel/horizon

Horizonはpcntlが必須です。ないと以下のようなエラーが表示されます。

$ composer require laravel/horizon
Using version ^2.0 for laravel/horizon
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - laravel/horizon v2.0.0 requires ext-pcntl * -> the requested PHP extension pcntl is missing from your system.
    - laravel/horizon 2.0.x-dev requires ext-pcntl * -> the requested PHP extension pcntl is missing from your system.
    - Installation request for laravel/horizon ^2.0 -> satisfiable by laravel/horizon[2.0.x-dev, v2.0.0].


Installation failed, reverting ./composer.json to its original content.

Dockerを使っている方はDockerファイルに以下を追加してからビルド&再起動で動く可能性があります。
どうにかしてpcntlをインストールしてください。

Dockerfile
(略)

RUN docker-php-ext-install pcntl
docker-compose up -d --build

セットアップ

Horizonをインストールします。

php artisan horizon:install

失敗したキューのためのテーブルを作成します。

php artisan queue:failed-table

php artisan migrate

Horizonの準備は以上です!

動かしてみる

Horizonを起動します。

php artisan horizon

/horizon にアクセスすると、ダッシュボードが表示されるはずです。

この状態で/test/sampletext3にアクセスしてみます。

storage/logs/laravel-2018-12-11.log
[2018-12-11 **:**:**] local.INFO: It's work! | sampletext3

ログが出力されていたら成功です。
おつかれさまでした👏

あとはもっとカスタマイズしたり、exit(1)で異常終了させたりして遊べます。
失敗したジョブ一覧から失敗したジョブをもう一度動かしてみることも可能です。

Screen Shot 2018-12-11 at 2.47.52.png

4. さいごに

非同期処理はLaravelがきちんとお世話してくれるので、簡単に実装できることがわかりました。
あとはSupervisorなどを用いてよしなにやればきちんと動くはずです。

動かしてみるだけでしたが、Horizonについてもご紹介しました。
Horizonにはその他認証、待ち状態が長いときの通知など機能がもりもりなので、ぜひ公式のドキュメントをチェックしてみてください。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23