はじめに

LaravelのConcurrencyファサードは、現在コミュニティのフィードバックを集めている間、ベータ版です。

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

同時実行の互換性

Laravel 10.xアプリケーションからLaravel 11.xにアップグレードした場合、アプリケーションのconfig/app.php設定ファイルのproviders配列にConcurrencyServiceProviderを追加する必要があるかもしれません:

  1. 'providers' => ServiceProvider::defaultProviders()->merge([
  2. /*
  3. * Package Service Providers...
  4. */
  5. Illuminate\Concurrency\ConcurrencyServiceProvider::class,
  6. /*
  7. * Application Service Providers...
  8. */
  9. App\Providers\AppServiceProvider::class,
  10. App\Providers\AuthServiceProvider::class,
  11. // App\Providers\BroadcastServiceProvider::class,
  12. App\Providers\EventServiceProvider::class,
  13. App\Providers\RouteServiceProvider::class,
  14. ])->toArray(),

動作の仕組み

Laravelは、指定されたクロージャをシリアライズし、それを隠れたArtisan CLIコマンドにディスパッチすることで同時実行を実現します。このコマンドはクロージャをアンシリアライズし、自身のPHPプロセス内で呼び出します。クロージャが呼び出された後、結果の値は親プロセスにシリアライズされて戻されます。

  1. `````fork`````ドライバーは、デフォルトの`````process`````ドライバーと比較してパフォーマンスが向上しますが、PHPCLIコンテキスト内でのみ使用できます。なぜなら、PHPWebリクエスト中にフォークをサポートしていないからです。`````fork`````ドライバーを使用する前に、`````spatie/fork`````パッケージをインストールする必要があります:
  2. ``````bash
  3. composer require spatie/fork
  4. `
  1. <a name="running-concurrent-tasks"></a>
  2. ## 同時タスクの実行
  3. 同時タスクを実行するには、`````Concurrency`````ファサードの`````run`````メソッドを呼び出すことができます。`````run`````メソッドは、子PHPプロセス内で同時に実行されるべきクロージャの配列を受け取ります:
  4. ``````php
  5. use Illuminate\Support\Facades\Concurrency;
  6. use Illuminate\Support\Facades\DB;
  7. [$userCount, $orderCount] = Concurrency::run([
  8. fn () => DB::table('users')->count(),
  9. fn () => DB::table('orders')->count(),
  10. ]);
  11. `

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

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

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

  1. php artisan config:publish concurrency

同時タスクの遅延実行

クロージャの配列を同時に実行したいが、それらのクロージャから返される結果には興味がない場合は、deferメソッドの使用を検討すべきです。deferメソッドが呼び出されると、指定されたクロージャは即座には実行されません。代わりに、LaravelはHTTPレスポンスがユーザーに送信された後にクロージャを同時に実行します:

  1. use App\Services\Metrics;
  2. use Illuminate\Support\Facades\Concurrency;
  3. Concurrency::defer([
  4. fn () => Metrics::report('users'),
  5. fn () => Metrics::report('orders'),
  6. ]);