Diese Bibliothek bietet einen kleinen und einfachen Wrapper für die PCNTL-Erweiterung von PHP. Es ermöglicht die parallele Ausführung verschiedener Prozesse mit einer benutzerfreundlichen API.
Wir investieren viele Ressourcen in die Erstellung erstklassiger Open-Source-Pakete. Sie können uns unterstützen, indem Sie eines unserer kostenpflichtigen Produkte kaufen.
Wir freuen uns sehr, dass Sie uns eine Postkarte aus Ihrer Heimatstadt schicken und erwähnen, welches unserer Pakete Sie verwenden. Unsere Adresse finden Sie auf unserer Kontaktseite. Wir veröffentlichen alle erhaltenen Postkarten auf unserer virtuellen Postkartenwand.
Sie können das Paket über Composer installieren:
composer require spatie/async
use Spatie Async Pool ;
$ pool = Pool:: create ();
foreach ( $ things as $ thing ) {
$ pool -> add ( function () use ( $ thing ) {
/ / Do a thing
})-> then ( function ( $ output ) {
/ / Handle success
})-> catch ( function ( Throwable $ exception ) {
/ / Handle exception
});
}
$ pool -> wait ();
Beim Erstellen asynchroner Prozesse wird eine Instanz von ParallelProcess
zurückgegeben. Sie können einem Prozess die folgenden Ereignis-Hooks hinzufügen.
$ pool
-> add ( function () {
/ / ...
})
-> then ( function ( $ output ) {
/ / On success , `$output` is returned by the process or callable you passed to the queue .
})
-> catch ( function ( $ exception ) {
/ / When an exception is thrown from within a process , it 's caught and passed here.
})
-> timeout ( function () {
/ / A process took too long to finish.
})
;
Anstatt Methoden für das $pool
-Objekt zu verwenden, können Sie auch die Hilfsfunktionen async
und await
verwenden.
use Spatie Async Pool ;
$ pool = Pool:: create ();
foreach ( range ( 1 , 5 ) as $ i ) {
$ pool [] = async ( function () {
usleep ( random_int ( 10 , 1000 ));
return 2 ;
})-> then ( function ( int $ output ) {
$ this -> counter += $ output ;
});
}
await ( $ pool );
Wenn eine Exception
oder Error
innerhalb eines untergeordneten Prozesses ausgelöst wird, kann sie pro Prozess abgefangen werden, indem in der ->catch()
Methode ein Rückruf angegeben wird.
$ pool
-> add ( function () {
/ / ...
})
-> catch ( function ( $ exception ) {
/ / Handle the thrown exception for this child process.
})
;
Wenn kein Fehlerhandler hinzugefügt wird, wird der Fehler im übergeordneten Prozess beim Aufruf von await()
oder $pool->wait()
ausgegeben.
Wenn der untergeordnete Prozess unerwartet stoppt, ohne ein Throwable
auszulösen, wird die in stderr
geschriebene Ausgabe umschlossen und als SpatieAsyncParallelError
im übergeordneten Prozess ausgegeben.
Durch Typhinweise für die catch
-Funktionen können Sie mehrere Fehlerhandler bereitstellen, jeweils für einzelne Fehlertypen.
$ pool
-> add ( function () {
throw new MyException ( ' test ' );
})
-> catch ( function ( MyException $ e ) {
/ / Handle `MyException`
})
-> catch ( function ( OtherException $ e ) {
/ / Handle `OtherException`
});
Beachten Sie, dass, sobald eine Ausnahme behandelt wird, keine anderen Handler mehr ausgelöst werden
$ pool
-> add ( function () {
throw new MyException ( ' test ' );
})
-> catch ( function ( MyException $ e ) {
/ / This one is triggerd when `MyException` is thrown
})
-> catch ( function ( Exception $ e ) {
/ / This one is not triggerd , even though `M yException ` extends `E xception `
});
Wenn Sie einen Pool vorzeitig stoppen müssen, weil die von ihm ausgeführte Aufgabe von einem der untergeordneten Prozesse abgeschlossen wurde, können Sie die Methode $pool->stop()
verwenden. Dadurch wird verhindert, dass der Pool weitere Prozesse startet.
use Spatie Async Pool ;
$ pool = Pool:: create ();
/ / Generate 10 k processes generating random numbers
for ( $ i = 0 ; $ i < 10000 ; $ i ++) {
$ pool -> add ( function () use ( $ i ) {
return rand ( 0 , 100 );
})-> then ( function ( $ output ) use ( $ pool ) {
/ / If one of them randomly picks 100 , end the pool early .
if ( $ output === 100 ) {
$ pool -> stop ();
}
});
}
$ pool -> wait ();
Beachten Sie, dass ein Pool nach dem Stoppen unbrauchbar wird und bei Bedarf ein neuer Pool erstellt werden sollte.
Standardmäßig verwendet der Pool php
um seine untergeordneten Prozesse auszuführen. Sie können eine andere Binärdatei wie folgt konfigurieren:
Pool:: create ()
-> withBinary ( ' /path/to/php ' );
Neben der Verwendung von Abschlüssen können Sie auch mit einer Task
arbeiten. Eine Task
ist in Situationen nützlich, in denen Sie mehr Einrichtungsarbeit im untergeordneten Prozess benötigen. Da ein untergeordneter Prozess immer aus dem Nichts gebootet wird, ist es wahrscheinlich, dass Sie z. B. initialisieren möchten. den Abhängigkeitscontainer, bevor Sie die Aufgabe ausführen. Die Task
Klasse erleichtert dies.
use Spatie Async Task ;
class MyTask extends Task
{
public function configure ()
{
/ / Setup eg . dependency container , load config , ...
}
public function run ()
{
/ / Do the real work here.
}
}
/ / Add the task to the pool
$ pool -> add ( new MyTask ());
Wenn Sie die Logik Ihrer Aufgabe kapseln, aber kein vollständiges Task
erstellen möchten, können Sie auch ein aufrufbares Objekt an den Pool
übergeben.
class InvokableClass
{
/ / ...
public function __invoke ()
{
/ / ...
}
}
$ pool -> add ( new InvokableClass ( / * ... * / ));
Es steht Ihnen frei, so viele Pools zu erstellen, wie Sie möchten. Jeder Pool verfügt über eine eigene Warteschlange mit Prozessen, die er verarbeiten wird.
Ein Pool kann vom Entwickler konfiguriert werden:
use Spatie Async Pool ;
$ pool = Pool:: create ()
/ / The maximum amount of processes which can run simultaneously.
-> concurrency ( 20 )
/ / The maximum amount of time a process may take to finish in seconds
/ / ( decimal places are supported for more granular timeouts ) .
-> timeout ( 15 )
/ / Configure which autoloader sub processes should use.
-> autoload ( __DIR__ . ' /../../vendor/autoload.php ' )
/ / Configure how long the loop should sleep before re - checking the process statuses in microseconds .
-> sleepTime ( 50000 )
;
Wenn die erforderlichen Erweiterungen ( pcntl
und posix
) nicht in Ihrer aktuellen PHP-Laufzeit installiert sind, greift der Pool
automatisch auf die synchrone Ausführung von Aufgaben zurück.
Die Pool
-Klasse verfügt über eine statische Methode isSupported
die Sie aufrufen können, um zu überprüfen, ob Ihre Plattform asynchrone Prozesse ausführen kann.
Wenn Sie eine Task
zum Ausführen von Prozessen verwenden, wird bei der Ausführung im synchronen Modus nur die run
dieser Aufgaben aufgerufen.
Wenn Sie dieses Paket verwenden, fragen Sie sich wahrscheinlich, was unter der Oberfläche passiert.
Wir verwenden die symfony/process
Komponente, um untergeordnete Prozesse in PHP zu erstellen und zu verwalten. Indem wir untergeordnete Prozesse im laufenden Betrieb erstellen, können wir PHP-Skripte parallel ausführen. Diese Parallelität kann die Leistung erheblich verbessern, wenn mehrere synchrone Aufgaben bearbeitet werden, die nicht wirklich aufeinander warten müssen. Indem diesen Aufgaben ein separater Prozess zur Ausführung zugewiesen wird, kann das zugrunde liegende Betriebssystem dafür sorgen, dass sie parallel ausgeführt werden.
Beim dynamischen Starten von Prozessen gibt es eine Einschränkung: Sie müssen sicherstellen, dass nicht zu viele Prozesse gleichzeitig ausgeführt werden, da die Anwendung sonst abstürzen könnte. Die von diesem Paket bereitgestellte Pool
-Klasse kümmert sich um die Abwicklung beliebig vieler Prozesse, indem sie diese nach Möglichkeit plant und ausführt.
Das ist der Teil, den async()
oder $pool->add()
übernimmt. Schauen wir uns nun an, was await()
oder $pool->wait()
bewirkt.
Wenn mehrere Prozesse erzeugt werden, kann jeder eine eigene Zeit bis zum Abschluss haben. Ein Prozess könnte z.B. muss auf einen HTTP-Aufruf warten, während der andere große Datenmengen verarbeiten muss. Manchmal gibt es auch Punkte in Ihrem Code, die warten müssen, bis das Ergebnis eines Prozesses zurückgegeben wird.
Aus diesem Grund müssen wir zu einem bestimmten Zeitpunkt warten: bis alle Prozesse in einem Pool abgeschlossen sind, damit wir sicher sein können, fortzufahren, ohne versehentlich die untergeordneten Prozesse zu beenden, die noch nicht abgeschlossen sind.
Das Warten auf alle Prozesse erfolgt mithilfe einer while
Schleife, die wartet, bis alle Prozesse abgeschlossen sind. Die Bestimmung, wann ein Prozess abgeschlossen ist, erfolgt mithilfe eines Listeners für das SIGCHLD
Signal. Dieses Signal wird ausgegeben, wenn ein untergeordneter Prozess vom Betriebssystemkernel abgeschlossen wird. Ab PHP 7.1 gibt es eine viel bessere Unterstützung für das Abhören und Verarbeiten von Signalen, wodurch dieser Ansatz leistungsfähiger ist als z. Verwendung von Prozessgabeln oder Sockets für die Kommunikation. Mehr darüber können Sie hier lesen.
Wenn ein Prozess abgeschlossen ist, wird sein Erfolgsereignis ausgelöst, das Sie mit der Funktion ->then()
einbinden können. Wenn ein Prozess fehlschlägt oder eine Zeitüberschreitung auftritt, aktualisiert die Schleife gleichermaßen den Status dieses Prozesses und geht weiter. Wenn alle Prozesse abgeschlossen sind, erkennt die while-Schleife, dass nichts mehr zu warten ist, und stoppt. Dies ist der Moment, in dem Ihr übergeordneter Prozess weiterhin ausgeführt werden kann.
Wir haben einen Blogbeitrag geschrieben, der weitere Informationen zu Anwendungsfällen für dieses Paket enthält und Vergleiche mit anderen asynchronen PHP-Bibliotheken wie ReactPHP und Amp anstellt: http://stitcher.io/blog/asynchronous-php.
composer test
Weitere Informationen zu den letzten Änderungen finden Sie im CHANGELOG.
Weitere Informationen finden Sie unter BEITRAGEN.
Wenn Sie einen Sicherheitsfehler gefunden haben, senden Sie bitte eine E-Mail an [email protected], anstatt den Issue-Tracker zu verwenden.
Es steht Ihnen frei, dieses Paket zu verwenden, aber wenn es in Ihre Produktionsumgebung gelangt, würden wir uns sehr freuen, wenn Sie uns eine Postkarte aus Ihrer Heimatstadt schicken und erwähnen, welches unserer Pakete Sie verwenden.
Unsere Adresse lautet: Spatie, Kruikstraat 22, 2018 Antwerpen, Belgien.
Wir veröffentlichen alle erhaltenen Postkarten auf unserer Firmenwebsite.
Die MIT-Lizenz (MIT). Weitere Informationen finden Sie in der Lizenzdatei.