Einleitung: Warum Parallelität in PHP kein Mythos ist
\nPHP gilt traditionell als synchrone Sprache, bei der jede Anfrage sequenziell verarbeitet wird. Moderne Anwendungen – von der Videoverarbeitung bis zum Parsen großer Datenmengen – erfordern jedoch die gleichzeitige Ausführung mehrerer Aufgaben. Ohne Parallelität riskieren Sie, an eine "Performance-Wand" zu stoßen, bei der selbst ein leistungsstarker Server untätig ist, während er auf den Abschluss von E/A-Operationen wartet.
\nIn diesem Artikel behandeln wir fortgeschrittene Techniken für die Arbeit mit Parallelität in PHP: von Systemaufrufen bis hin zu Erweiterungen auf Kernel-Ebene. Sie erfahren, wie Sie PHP parallel arbeiten lassen, ohne die Kontrolle über die Ressourcen zu verlieren.
\n\n1. Grundlagen: Prozesse vs. Threads in PHP
\nBevor wir in den Code eintauchen, ist es wichtig, den Unterschied zwischen Prozessen und Threads im Kontext von PHP zu verstehen.
\n- \n
- Prozesse – isolierte Instanzen, jede mit eigenem Speicher. Werden über
pcntl_fork()erstellt. Geeignet für schwere Aufgaben, erfordern aber Interprozesskommunikation (IPC). \n - Threads – leichtgewichtige "Unteraufgaben" innerhalb eines Prozesses, die sich den Speicher teilen. Werden über die Erweiterung
pthreadsimplementiert. Ideal für die Arbeit mit gemeinsamen Daten, erfordern aber Synchronisation. \n
Auf fortgeschrittenem Niveau ist es wichtig, beide Ansätze kombinieren zu können. Verwenden Sie beispielsweise Forks zur Isolierung kritischer Aufgaben und Threads für die parallele Verarbeitung innerhalb eines Kontextes.
\n\n1.1 Parallele Prozesse mit pcntl_fork()
\nDer Systemaufruf pcntl_fork() erstellt einen untergeordneten Prozess, der den Speicher des übergeordneten Prozesses kopiert. Betrachten wir ein Beispiel für die parallele Verarbeitung mehrerer URLs:
<?php\n$urls = ['https://api.example.com/data1', 'https://api.example.com/data2', 'https://api.example.com/data3'];\n$pids = [];\n\nforeach ($urls as $url) {\n $pid = pcntl_fork();\n if ($pid == -1) {\n die('Prozess konnte nicht erstellt werden');\n } elseif ($pid) {\n // Übergeordneter Prozess: PID speichern\n $pids[] = $pid;\n } else {\n // Untergeordneter Prozess: Download durchführen\n $data = file_get_contents($url);\n file_put_contents('/tmp/' . md5($url) . '.json', $data);\n exit(0); // Untergeordneten Prozess beenden\n }\n}\n\n// Auf Abschluss aller Prozesse warten\nforeach ($pids as $pid) {\n pcntl_waitpid($pid, $status);\n}\necho "Alle URLs wurden parallel verarbeitet!";\n?>\nWichtig: Nach fork() erben die untergeordneten Prozesse alle geöffneten Dateideskriptoren und Datenbankverbindungen. Schließen Sie diese explizit im untergeordneten Prozess, um Konflikte zu vermeiden.
\n\n2. Asynchrone Aufgaben mit ReactPHP und Amp
\nFür Webanwendungen, bei denen Reaktivität wichtig ist, verwenden Sie Bibliotheken mit ereignisgesteuerter Schleife. ReactPHP und Amp ermöglichen die Ausführung nicht-blockierender Operationen, ohne separate Prozesse zu erstellen.
\n\n2.1 Beispiel mit ReactPHP
\nInstallieren Sie die Bibliothek über Composer: composer require react/react. Unten sehen Sie einen asynchronen HTTP-Client, der drei Anfragen gleichzeitig sendet:
<?php\nrequire 'vendor/autoload.php';\n\nuse React\\EventLoop\\Factory;\nuse React\\HttpClient\\Client;\n\n$loop = Factory::create();\n$client = new Client($loop);\n\n$urls = ['http://example.com', 'http://example.org', 'http://example.net'];\n$promises = [];\n\nforeach ($urls as $url) {\n $request = $client->request('GET', $url);\n $request->on('response', function ($response) use ($url) {\n echo "Antwort von {$url}: " . $response->getCode() . PHP_EOL;\n });\n $request->end();\n}\n\n$loop->run();\n?>\nReactPHP erstellt eine einzige Ereignisschleife, die alle Anfragen ohne Blockierung verarbeitet. Dies ist ideal für API-Gateways oder Microservices, bei denen Antwortgeschwindigkeit wichtig ist.
\n\n3. Thread-Verwaltung mit pthreads (ZTS-Build)
\nDie Erweiterung pthreads ist der einzige Weg, um echte Multithreading-Fähigkeiten in PHP zu erhalten.
Blogs
Buchempfehlungen
Lesen Sie auch
HTTP-Client in Go: Fortgeschrittene Techniken für die Arbeit mit Anfragen
LINQ-Abfragen für DataTable in C#: Ultimativer Leitfaden mit Beispielen
Caching in Java: Redis, Memcached und integrierte Lösungen von A bis Z
BDD in Kotlin: Wie man Tests schreibt, die sogar Manager verstehen
Arbeiten mit JSON in JavaScript: Parsen und Serialisieren von Daten