Skip to content

並行処理

はじめに

Warning

LaravelのConcurrencyファサードは現在ベータ版であり、コミュニティからのフィードバックを収集しています。

時には、互いに依存しないいくつかの遅いタスクを実行する必要があるかもしれません。多くの場合、これらのタスクを並行して実行することで、大幅なパフォーマンス向上を実現できます。LaravelのConcurrencyファサードは、クロージャを並行して実行するためのシンプルで便利なAPIを提供します。

仕組み

Laravelは、与えられたクロージャをシリアライズし、それらをバックグラウンドで実行されるArtisan CLIコマンドにディスパッチすることで並行処理を実現します。このコマンドは、クロージャをアンシリアライズし、独自のPHPプロセス内で呼び出します。クロージャが呼び出された後、結果の値は親プロセスにシリアライズされて戻されます。

Concurrencyファサードは、process(デフォルト)、forksyncの3つのドライバをサポートしています。

forkドライバは、デフォルトのprocessドライバよりもパフォーマンスが向上しますが、PHPのCLIコンテキスト内でのみ使用できます。これは、PHPがWebリクエスト中にフォークをサポートしていないためです。forkドライバを使用する前に、spatie/forkパッケージをインストールする必要があります:

composer require spatie/fork

syncドライバは、すべての並行処理を無効にして、与えられたクロージャを親プロセス内で順次実行したい場合、主にテスト時に有用です。

並行タスクの実行

並行タスクを実行するには、Concurrencyファサードのrunメソッドを呼び出します。runメソッドは、子PHPプロセスで同時に実行されるべきクロージャの配列を受け取ります:

use Illuminate\Support\Facades\Concurrency;
use Illuminate\Support\Facades\DB;

[$userCount, $orderCount] = Concurrency::run([
    fn () => DB::table('users')->count(),
    fn () => DB::table('orders')->count(),
]);

特定のドライバを使用するには、driverメソッドを使用できます:

$results = Concurrency::driver('fork')->run(...);

または、デフォルトの並行処理ドライバを変更したい場合は、config:publish Artisanコマンドを介してconcurrency設定ファイルを公開し、ファイル内のdefaultオプションを更新する必要があります:

php artisan config:publish concurrency

並行タスクの延期

クロージャの配列を並行して実行したいが、それらのクロージャが返す結果に興味がない場合は、deferメソッドの使用を検討してください。deferメソッドが呼び出されると、与えられたクロージャはすぐに実行されません。代わりに、LaravelはHTTPレスポンスがユーザーに送信された後にクロージャを並行して実行します:

use App\Services\Metrics;
use Illuminate\Support\Facades\Concurrency;

Concurrency::defer([
    fn () => Metrics::report('users'),
    fn () => Metrics::report('orders'),
]);

ユーザーノート