Wat is concurrency?
Wanneer je meerdere taken die niet van elkaar afhankelijk zijn — zoals requests naar meerdere externe API’s of database-aggregaties — na elkaar uitvoert, is de totale tijd de som van alle afzonderlijke verwerkingstijden. Voer je ze tegelijk uit, dan wordt de totale tijd teruggebracht tot die van de langzaamste taak. LaravelsConcurrency-facade maakt zulke parallelle uitvoering mogelijk met een eenvoudige API.
De
Concurrency-facade is geïntroduceerd in Laravel 11 en is ook in Laravel 13 nog beschikbaar.
De standaarddriver gebruikt PHP-childprocessen en werkt dus zonder extra packages.Hoe het werkt
DeConcurrency-facade serialiseert de doorgegeven closures, stuurt ze naar een verborgen Artisan-commando en voert ze elk uit in een apart PHP-proces.
Zodra de verwerking klaar is, wordt de returnwaarde geserialiseerd en teruggestuurd naar het parent-proces.
Er zijn drie drivers beschikbaar.
Basisgebruik
Concurrency::run()
Als je een array van closures aan derun()-methode doorgeeft, worden deze parallel uitgevoerd.
Als resultaat ontvang je een array met de returnwaarden van elke closure.
Een driver kiezen
Wil je een specifieke driver gebruiken, dan geef je die op met dedriver()-methode.
default-optie aan.
De fork-driver gebruiken
Defork-driver is sneller dan de process-driver, maar kan alleen worden gebruikt in de PHP CLI-omgeving (Artisan-commando’s en queue workers).
Binnen webrequests kun je hem niet gebruiken.
Installeer vóór gebruik het spatie/fork-package.
Geen resultaat nodig: Concurrency::defer()
Als je niet geïnteresseerd bent in het resultaat en de taken op de achtergrond wilt uitvoeren nadat de HTTP-response is verstuurd, gebruik je dedefer()-methode.
defer() aanroept, worden de closures nog niet uitgevoerd.
Ze worden parallel uitgevoerd nadat de HTTP-response naar de gebruiker is verzonden.
Praktijkvoorbeeld: meerdere externe API’s tegelijk aanroepen
Neem als voorbeeld een dashboard van een webshop dat informatie ophaalt uit drie API’s: voorraadbeheer, verkoopcijfers en verzendstatus.Sequentiële uitvoering (vóór verbetering)
Parallelle uitvoering (na verbetering)
Meerdere database-aggregaties tegelijk uitvoeren
Configuratie voor tests
In de testomgeving voert desync-driver de closures sequentieel uit.
Er zijn geen opstartkosten voor processen, waardoor je tests sneller worden.
.env.testing.
Aandachtspunten
Beperkingen van closures
Beperkingen van closures
Closures worden geserialiseerd en doorgegeven aan het childproces.
Objecten die niet geserialiseerd kunnen worden (databaseverbindingen, file handles, resources enzovoort) kun je niet van buiten de closure capturen.
Maak benodigde objecten binnen de closure opnieuw aan.
Overhead van de process-driver
Overhead van de process-driver
De
process-driver heeft opstartkosten voor childprocessen. Als de taak zelf heel kort is (enkele milliseconden of minder), levert parallelle uitvoering mogelijk geen snelheidswinst op.
Parallellisatie loont vooral bij taken die 100 ms of langer duren, zoals HTTP-requests of database-aggregaties.Beperkingen van de fork-driver
Beperkingen van de fork-driver
De
fork-driver forkt PHP-processen en kan daarom niet worden gebruikt tijdens webrequests (FPM of Apache).
Gebruik hem alleen binnen Artisan-commando’s of queue workers.Omgaan met exceptions
Omgaan met exceptions
Als er tijdens de parallelle uitvoering een exception optreedt, gooit
run() die exception opnieuw.
Wil je dat de andere taken doorgaan als één taak een exception veroorzaakt, gebruik dan try/catch binnen de closure.Volgende stap
Queues en jobs
Leer hoe je met queues en jobs taken asynchroon op de achtergrond uitvoert