イントロダクションIntroduction
Warning! Laravelの
Concurrency
ファサードは、現在ベータであり、コミュニティーのフィードバッグを集めています。[!WARNING]Laravel'sConcurrency
facade is currently in beta while we gather community feedback.
時には、互いに依存していない複数の低速タスクを実行する必要があるでしょう。多くの場合、タスクを同時実行することで大幅なパフォーマンス改善が実現できます。LaravelのConcurrency
ファサードは、クロージャを同時実行するためのシンプルで便利なAPIを提供します。Sometimes you may need to execute several slow tasks which do not depend on one another. In many cases, significant performance improvements can be realized by executing the tasks concurrently. Laravel's Concurrency
facade provides a simple, convenient API for executing closures concurrently.
並列処理互換性Concurrency Compatibility
Laravel10.xのアプリケーションから、Laravel11.xへアップグレードした場合、アプリケーションのconfig/app.php
設定ファイルのproviders
配列へ、ConcurrencyServiceProvider
を追加する必要があるでしょう。If you upgraded to Laravel 11.x from a Laravel 10.x application, you may need to add the ConcurrencyServiceProvider
to the providers
array in your application's config/app.php
configuration file:
'providers' => ServiceProvider::defaultProviders()->merge([
/*
* パッケージサービスプロバイダ
*/
Illuminate\Concurrency\ConcurrencyServiceProvider::class, // [tl! add]
/*
* アプリケーションサービスプロバイダ
*/
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
])->toArray(),
いかに動作するかHow it Works
Laravelは指定クロージャをシリアライズし、隠しArtisan CLIコマンドへディスパッチすることで並行処理を実現します。Artisan CLIコマンドはクロージャのシリアライズを解除し、自身のPHPプロセス内でそれを呼び出します。クロージャが呼び出された後、結果の値はシリアライズされて親プロセスに戻されます。Laravel achieves concurrency by serializing the given closures and dispatching them to a hidden Artisan CLI command, which unserializes the closures and invokes it within its own PHP process. After the closure has been invoked, the resulting value is serialized back to the parent process.
Concurrency
ファサードは、3つのドライバをサポートします。process
(デフォルト)、fork
、sync
です。The Concurrency
facade supports three drivers: process
(the default), fork
, and sync
.
fork
ドライバは、デフォルトのprocess
ドライバに比べパフォーマンスが向上しますが、PHPのCLI コンテキストでのみ使用できます。fork
ドライバを使用する前に、spatie/fork
パッケージをインストールする必要があります。The fork
driver offers improved performance compared to the default process
driver, but it may only be used within PHP's CLI context, as PHP does not support forking during web requests. Before using the fork
driver, you need to install the spatie/fork
package:
composer require spatie/fork
sync
ドライバは主にテスト中で使用し、すべての並列処理を無効にして、親プロセス内で与えられたクロージャを順番に実行したいときに便利です。The sync
driver is primarily useful during testing when you want to disable all concurrency and simply execute the given closures in sequence within the parent process.
タスクの同時実行Running Concurrent Tasks
タスクを並列実行するには、Concurrency
ファサードのrun
メソッドを呼び出します。run
メソッドには、PHPの子プロセスで同時に実行するクロージャの配列を渡します。To run concurrent tasks, you may invoke the Concurrency
facade's run
method. The run
method accepts an array of closures which should be executed simultaneously in child PHP processes:
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
メソッドを使用します。To use a specific driver, you may use the driver
method:
$results = Concurrency::driver('fork')->run(...);
または、デフォルトの並列実行ドライバを変更するため、config:publish
Artisanコマンドでconcurrency
設定ファイルをリソース公開し、ファイル内のdefault
オプションを更新する必要があります。Or, to change the default concurrency driver, you should publish the concurrency
configuration file via the config:publish
Artisan command and update the default
option within the file:
php artisan config:publish concurrency
タスクの遅延実行Deferring Concurrent Tasks
クロージャの配列を並列実行したいが、それらのクロージャが返す結果には興味がない場合は、defer
メソッドの使用を検討すべきでしょう。defer
メソッドを呼び出すと、指定されたクロージャはすぐには実行されません。代わりに、LaravelはHTTPレスポンスがユーザーに送信された後に、クロージャを同時に実行します。If you would like to execute an array of closures concurrently, but are not interested in the results returned by those closures, you should consider using the defer
method. When the defer
method is invoked, the given closures are not executed immediately. Instead, Laravel will execute the closures concurrently after the HTTP response has been sent to the user:
use App\Services\Metrics;
use Illuminate\Support\Facades\Concurrency;
Concurrency::defer([
fn () => Metrics::report('users'),
fn () => Metrics::report('orders'),
]);