Concorrenza

Introduzione

La facade Concurrency di Laravel è attualmente in beta mentre raccogliamo feedback dalla comunità.

A volte potresti aver bisogno di eseguire diverse attività lente che non dipendono l’una dall’altra. In molti casi, si possono ottenere miglioramenti significativi delle prestazioni eseguendo le attività in modo concorrente. La facade Concurrency di Laravel fornisce un’API semplice e comoda per eseguire closure in modo concorrente.

Compatibilità della Concorrenza

Se hai aggiornato a Laravel 11.x da un’applicazione Laravel 10.x, potrebbe essere necessario aggiungere il ConcurrencyServiceProvider all’array providers nel file di configurazione config/app.php della tua applicazione:

'providers' => ServiceProvider::defaultProviders()->merge([
    /*
     * Provider di pacchetti...
     */
    Illuminate\Concurrency\ConcurrencyServiceProvider::class, // [tl! add]

    /*
     * Provider di applicazione...
     */
    App\Providers\AppServiceProvider::class,
    App\Providers\AuthServiceProvider::class,
    // App\Providers\BroadcastServiceProvider::class,
    App\Providers\EventServiceProvider::class,
    App\Providers\RouteServiceProvider::class,
])->toArray(),

Come Funziona

Laravel gestisce la concorrenza serializzando le closure fornite e inviandole a un comando nascosto di Artisan CLI, che deserializza le closure e le esegue all’interno del proprio processo PHP. Dopo che la closure è stata eseguita, il valore risultante viene serializzato nuovamente nel processo principale.

La facade Concurrency supporta tre driver: process (predefinito), fork e sync.

Il driver fork offre prestazioni migliori rispetto al driver predefinito process, ma può essere utilizzato solo nel contesto della CLI di PHP, poiché PHP non supporta il fork durante le richieste web. Prima di usare il driver fork, è necessario installare il pacchetto spatie/fork:

composer require spatie/fork

Il driver sync è principalmente utile durante i test quando si desidera disabilitare tutta la concorrenza ed eseguire semplicemente le closure fornite in sequenza all’interno del processo principale.

Esecuzione di Task Concorrenti

Per eseguire task concorrenti, puoi chiamare il metodo run della facade Concurrency. Il metodo run accetta un array di closures che devono essere eseguite simultaneamente in processi PHP figli:

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

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

Per usare un driver specifico, puoi usare il metodo driver:

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

Oppure, per cambiare il driver di concorrenza predefinito, devi pubblicare il file di configurazione concurrency tramite il comando Artisan config:publish e aggiornare l’opzione default all’interno del file:

php artisan config:publish concurrency

Differire le attività concorrenti

Se desideri eseguire un array di closure in modo concorrente, ma non ti interessano i risultati restituiti da queste closure, dovresti considerare l’uso del metodo defer. Quando viene invocato il metodo defer, le closure fornite non vengono eseguite immediatamente. Invece, Laravel eseguirà le closure in modo concorrente dopo che la risposta HTTP è stata inviata all’utente:

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

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

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *