0Pricing
PHP Academy · Lektion

Das PHP-Konkurrenzmodell

Verstehen Sie blockierendes I/O und wo Async hilfreich ist.

Das PHP-Konkurrenzmodell ist eine kostenlose PHP Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des PHP Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der PHP Academy-Kurs umfasst insgesamt 4 Lektionen.

PHP ist standardmäßig synchron

Klassisches PHP verarbeitet pro Prozess eine Anfrage von oben nach unten und verwendet dabei blockierende I/O. Ein file_get_contents()-Aufruf für eine langsame API hält das gesamte Skript an, bis die Bytes eintreffen. Das Shared-Nothing-Modell (ein neuer Prozess pro Anfrage, dessen Zustand am Ende verworfen wird) ist wunderbar einfach — bedeutet aber auch, dass ein einzelner Worker immer nur eine Sache gleichzeitig erledigen kann. Diese Lektion zeigt, wo das problematisch wird und wo Async hilft.

Blockierende I/O gemessen

Beobachten Sie, wie die verstrichene Zeit von Wartezeiten und nicht von Berechnungen dominiert wird. Drei sequenzielle Anfragen mit jeweils einer Sekunde Dauer benötigen etwa drei Sekunden, obwohl die CPU die ganze Zeit untätig ist.

<?php
$start = microtime(true);
foreach (['a', 'b', 'c'] as $job) {
    usleep(1_000_000); // simulate a 1s blocking network call
    echo "done $job\n";
}
printf("elapsed: %.2fs\n", microtime(true) - $start); // ~3.00s

CPU-bound oder I/O-bound

Konkurrenz hilft nur bei I/O-bound-Arbeit — also bei Zeit, die mit dem Warten auf Netzwerk, Datenträger oder Datenbank verbracht wird. Bei CPU-bound-Arbeit (Hashing, Bildgrößenänderung, Parsen) ist ein einzelner Thread bereits ausgelastet; Async fügt lediglich Scheduling-Overhead hinzu. Analysieren Sie zuerst:

  • Viele langsame HTTP-Aufrufe oder Datenbankabfragen → Async bringt große Vorteile.
  • Enge numerische Schleifen → Verwenden Sie Parallelität (Prozesse/Threads) statt einer Event-Loop.

Wie PHP bisher skaliert hat

Historisch skalierte PHP über Parallelität auf Prozessebene: PHP-FPM hält einen Pool von Worker-Prozessen; jeder verarbeitet eine Anfrage nach der anderen, während das Betriebssystem sie multiplexiert. Das ist echte Parallelität zwischen Anfragen, bietet innerhalb einer Anfrage jedoch nichts — mit gewöhnlichem blockierendem Code können Sie weiterhin nicht 50 API-Aufrufe innerhalb eines Handlers parallel ausführen.

Das Prinzip der Event-Schleife

Asynchrones PHP führt eine Event-Schleife ein: einen einzelnen Thread, der E/A-Operationen als nicht blockierend registriert und dann in stream_select()/epoll wartet, bis eine davon bereit ist, und Callbacks ausführt, sobald Daten eintreffen. Ein Thread verwaltet Tausende von Sockets, weil er nie untätig auf einen einzelnen wartet.

<?php
// Conceptual loop: poll many non-blocking streams at once
$streams = openManyNonBlockingSockets();
while ($streams) {
    $read = $streams; $write = $except = [];
    stream_select($read, $write, $except, null); // sleeps until ANY is ready
    foreach ($read as $s) {
        handleReadyStream($s); // runs only the sockets that have data now
    }
}

Kooperativ statt präemptiv

Asynchrones PHP ist kooperativ: Aufgaben laufen, bis sie an einem E/A-Punkt freiwillig die Kontrolle abgeben. Es gibt keine Präemption, daher bringt ein langer blockierender Aufruf oder eine enge CPU-Schleife die gesamte Event-Schleife zum Stillstand — alle anderen Aufgaben kommen nicht mehr zum Zug. Goldene Regel: Rufen Sie innerhalb einer Aufgabe der Event-Schleife niemals blockierende Funktionen (sleep, blockierendes PDO, file_get_contents) auf. Verwenden Sie die asynchronen Entsprechungen der Schleife.

Drei Ansätze in PHP

Modernes PHP bietet ein mehrschichtiges Toolkit:

  • Fibers (PHP 8.1, Kernfunktion) — ein Low-Level-Primitiv zum Anhalten und Fortsetzen eines Aufruf-Stacks. Der Baustein, kein vollständiges Framework.
  • ReactPHP / Amp — Event-Schleifen im Userland, die auf Streams (und inzwischen Fibers) basieren, für nicht blockierende E/A ohne Erweiterungen.
  • Swoole / OpenSwoole — eine C-Erweiterung, die Coroutines, einen hochperformanten Server und mit Hooks versehene blockierende Aufrufe bereitstellt.

Ermitteln Sie vor der Wahl einer Strategie, was zur Laufzeit verfügbar ist.

<?php
echo 'Fibers: ' . (class_exists('Fiber') ? 'yes' : 'no'), PHP_EOL;
echo 'Swoole ext: ' . (extension_loaded('swoole') ? 'yes' : 'no'), PHP_EOL;
echo 'parallel ext: ' . (extension_loaded('parallel') ? 'yes' : 'no'), PHP_EOL;
echo 'PHP ' . PHP_VERSION, PHP_EOL;

Promises modellieren zukünftige Werte

Vor Fibers stellte asynchrones PHP ausstehende Ergebnisse als Promises bereit: als Platzhalter für einen Wert, der später aufgelöst wird. Sie hängen mit then() Callbacks an. Das funktioniert, führt aber zu verschachtelten Ketten; Fibers ermöglichen es Bibliotheken, dies hinter einem synchron wirkenden await zu verbergen.

<?php
use React\Promise\Promise;

$promise = new Promise(function ($resolve) {
    // resolved later when I/O completes
    $resolve(42);
});
$promise->then(function ($value) {
    echo "got $value\n";
});

Nebenläufigkeit und Parallelität

Seien Sie präzise:

  • Nebenläufigkeit — viele Aufgaben sind in Bearbeitung und wechseln sich in einem Thread ab (Event-Schleife). Ideal für E/A.
  • Parallelität — viele Aufgaben werden auf mehreren Kernen gleichzeitig ausgeführt (Prozesse, die parallel-Erweiterung, Swoole-Task-Worker). Für CPU-Arbeit erforderlich.

Eine Event-Schleife bietet Nebenläufigkeit, nicht Parallelität. Der folgende Codeausschnitt zeigt Parallelität auf Prozessebene mit proc_open — drei Worker laufen gleichzeitig in separaten Betriebssystemprozessen.

<?php
$procs = [];
foreach (range(1, 3) as $i) {
    // Each worker is a separate OS process -> real parallelism
    $procs[] = proc_open(
        "php -r 'usleep(500000); echo \"worker $i done\\n\";'",
        [1 => ['pipe', 'w']], $pipes
    );
}
foreach ($procs as $p) { proc_close($p); }
echo "all workers launched in parallel\n";

Wann Sie NICHT auf Async setzen sollten

Asynchronität hat ihren Preis: Bei einem langlebigen Worker setzt PHP den Zustand zwischen Anfragen nicht mehr zurück, sodass Speicherlecks, statische Caches und veraltete Verbindungen zu Ihrem Problem werden. Wenn ein Request-Handler eine einzige DB-Abfrage ausführt und zurückkehrt, ist PHP-FPM einfacher und genauso schnell. Setzen Sie auf Async, wenn Sie I/O-Fan-out, WebSockets/Long Polling, Streaming oder einen persistenten Server benötigen.

Echte Parallelität: ext-parallel und Prozesse

Für CPU-intensives Fan-out kann PHP echte Parallelität auf Betriebssystemebene ausführen. Die parallel-Erweiterung startet Worker-Threads mit isoliertem Speicher; alternativ erzeugen proc_open/pcntl_fork Prozesse. Im Gegensatz zu einer Event-Schleife nutzen diese mehrere Kerne gleichzeitig — das richtige Werkzeug, wenn der Engpass in der Berechnung und nicht im Warten liegt.

<?php
// Requires ext-parallel — runs tasks on separate threads/cores
use parallel\Runtime;

$runtime = new Runtime();
$future = $runtime->run(function (): int {
    $sum = 0;
    for ($i = 0; $i < 1_000_000; $i++) $sum += $i; // CPU work on another core
    return $sum;
});
echo $future->value(), PHP_EOL;

Kurzer Test

Was passiert, wenn Sie innerhalb einer Aufgabe der Event-Schleife blockierendes sleep(2) aufrufen?

Zusammenfassung

Sie verfügen jetzt über ein mentales Modell der Nebenläufigkeit in PHP:

  • PHP ist standardmäßig synchron, blockierend und shared-nothing; FPM skaliert über Anfragen hinweg, nicht innerhalb einer einzelnen Anfrage.
  • Async unterstützt I/O-bound-Arbeit über eine einsträngige Event-Schleife mit nicht blockierenden Streams.
  • Das Modell ist kooperativ — blockieren Sie niemals die Schleife; lange CPU-Arbeit benötigt Parallelität, nicht Nebenläufigkeit.
  • Das PHP-Toolkit: Fibers (Primitiv), ReactPHP/Amp (Userland-Schleifen plus Promises), Swoole (Coroutine-Erweiterung).

Häufig gestellte Fragen

Ist die Lektion „Das PHP-Konkurrenzmodell“ kostenlos?

Ja — der vollständige Text von „Das PHP-Konkurrenzmodell“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des PHP Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der PHP Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Das PHP-Konkurrenzmodell“?

Verstehen Sie blockierendes I/O und wo Async hilfreich ist. Du übst PHP Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um PHP Academy zu starten?

Keine Vorkenntnisse erforderlich. PHP Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.

Wie lange dauert die Lektion „Das PHP-Konkurrenzmodell“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser PHP Academy-Lektion Code schreiben und ausführen?

Ja. Jede PHP Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Das PHP-Konkurrenzmodell
  2. PHP 8.1 Fibers
  3. Event Loops mit ReactPHP
  4. Hochleistungsserver mit Swoole
← Zurück zu PHP Academy