并发
这是一篇协同翻译的文章,你可以点击『我来翻译』按钮来参与翻译。
Concurrency
Introduction
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.
How it Works
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.
The Concurrency
facade supports three drivers: process
(the default), fork
, and sync
.
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
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
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(),
]);
To use a specific driver, you may use the driver
method:
$results = Concurrency::driver('fork')->run(...);
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
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'),
]);
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: